5

I want to dynamically deliver content and display hyperlinks, but it can’t be delivered dynamically and doesn’t work

let linkTitle = "Apple Link"
let linkURL = "http://www.apple.com"
let string = "[Apple Link](http://www.apple.com)"
            
Text(string)        // Not working

Text("[Apple Link](http://www.apple.com)")  // Working
            
Text("[\(linkTitle)](http://www.apple.com)")    // Working
            
Text("[\(linkTitle)](\(linkURL))")  // Not working
            
kgaidis
  • 12,375
  • 4
  • 70
  • 84
gaohomway
  • 842
  • 9
  • 17
  • hmm, does not work for me as well. You may have to resort to: "Link(linkTitle, destination: URL(string: linkURL)!)" – workingdog support Ukraine Jul 18 '21 at 07:49
  • @workingdog I am implementing hashtags(#) and mentions(@) Text very perfect, I only need to customize the URL Schemes, but unfortunately I can’t pass the string dynamically – gaohomway Jul 18 '21 at 08:06

4 Answers4

6

Short Answer

Wrap the string in AttributedString(markdown: my_string_here):

let string: String = "[Apple Link](http://www.apple.com)"
Text(try! AttributedString(markdown: string))

Extension

extension String {
  func toMarkdown() -> AttributedString {
    do {
      return try AttributedString(markdown: self)
    } catch {
      print("Error parsing Markdown for string \(self): \(error)")
      return AttributedString(self)
    }
  }
}

Long Answer

SwiftUI Text has multiple initializers.

For String:

init<S>(_ content: S) where S : StringProtocol

For AttributedString:

init(_ attributedContent: AttributedString)

When you declare a static string, Swift is able to guess whether the intent is to use a String or AttributedString (Markdown). However, when you use a dynamic string, Swift needs help in figuring out your intent.

As a result, with a dynamic string, you have to explicitly convert your String into an AttributedString:

try! AttributedString(markdown: string)
kgaidis
  • 12,375
  • 4
  • 70
  • 84
3

you can try this taken from: How to show HTML or Markdown in a SwiftUI Text? halfway down the page.

extension String {
    func markdownToAttributed() -> AttributedString {
        do {
            return try AttributedString(markdown: self) /// convert to AttributedString
        } catch {
            return AttributedString("Error parsing markdown: \(error)")
        }
    }
}
struct ContentView: View {
    let linkTitle = "Apple Link"
    let linkURL = "https://www.apple.com"
    let string = "[Apple Link](https://www.apple.com)"
       
    @State var textWithMarkdown = "[Apple Link](https://www.apple.com)"
    
    var body: some View {
        VStack {

            Text(textWithMarkdown.markdownToAttributed()) // <-- this works
            
            Text(string)        // Not working

            Text("[Apple Link](http://www.apple.com)")  // Working
                        
            Text("[\(linkTitle)](http://www.apple.com)")    // Working
                        
            Text("[\(linkTitle)](\(linkURL))")  // Not working
        }

    }
}
1

Add another .init in text.

struct ContentView: View {
    
    let linkTitle = "Apple Link"
    let linkURL = "http://www.apple.com"
    let string = "[Apple Link](http://www.apple.com)"
    
    var body: some View {
    
        Text(.init(string))     // <== Here!
        
        Text("[Apple Link](http://www.apple.com)")  // Working
        
        Text("[\(linkTitle)](http://www.apple.com)")    // Working
        
        Text(.init("[\(linkTitle)](\(linkURL))"))  // <== Here!
    }
}
Raja Kishan
  • 12,872
  • 2
  • 11
  • 29
0

is possible with Link or UIApplicarion.shared.open

struct ContentView: View {

let linkTitle = "Apple Link"
let linkURL = "http://www.apple.com"

var body: some View {
   
    VStack {
        Link(destination: URL(string: linkURL)!) {
            Text(linkTitle)
        }.padding()
        
        Text(linkTitle).onTapGesture {
            UIApplication.shared.open(URL(string: linkURL)!)
        }.foregroundColor(.blue)
    }
                
   
}

}

dig
  • 219
  • 1
  • 7
  • It’s a pity that Link can’t meet my needs. I’m implementing mentions(@) and hashtags(#). The Text is perfect. You only need to customize the URL Types. Unfortunately, you can’t dynamically pass strings. – gaohomway Jul 18 '21 at 08:04