skip to Main Content

I’m developing a SwiftUI app, where I want to insert inline image into Text view. For static content, I may use string interpolation like this:

Text("Hello, (Image(systemName: "pencil")) World! (Image(systemName: "pencil.circle"))")

The result would look like:

enter image description here

But in my case, the content may be dynamic. That is, I may receive the following string from server:

Hello #image(pencil) World! #image(pencil.circle)

I must parse the content dynamically and present the inline image with SwiftUI Text. Is this possible? I only wonder how to construct the string interpolation with image dynamically, the parsing of string is not my concern.

2

Answers


  1. You can pass a variable to the Image when you initialize it:

    var imageNameFromServer = "pencil"
    Text("Hello, world (Image(systemName: imageNameFromServer))")
    

    Update: Example of using many Text items:

    @ViewBuilder
    var longText: some View {
        (0...100).reduce(Text(""), { $0 + Text("($1)")})
    }
    
    Login or Signup to reply.
  2. This is quite an interesting problem!
    Here is an alternate way of achieving this.

    import SwiftUI
    
    struct ContentView: View {
        var body: some View {
            let serverString = "Hello #image(pencil) World!     #image(pencil.circle)"
            
            parse(serverString).reduce(Text("")) { (result, model) in
                return result + model.getSwiftUIView()
            }
        }
        
        func parse(_ serverString: String) -> [Model] {
            serverString.split(separator: " ", omittingEmptySubsequences: false).compactMap {
                Model(word: String($0))
            }
        }
    }
    
    struct Model {
        enum ViewType {
            case image, text
        }
        
        let type: ViewType
        let content: String
        
        init(word: String) {
            if word.hasPrefix("#image") {
                type = .image
                content = Model.replaceImagePatterns(input: String(word))
            } else {
                type = .text
                content = word
            }
        }
    
        func getSwiftUIView() -> Text {
            if type == .image {
                return Text("(Image(systemName: content))") + Text(" ")
            } else {
                return Text(content) + Text(" ")
            }
        }
        
        static func replaceImagePatterns(input: String) -> String {
            let pattern = "#image\((\w+(?:\.\w+)*)\)"
            let replacement = "$1"
    
            do {
                let regex = try NSRegularExpression(pattern: pattern, options: [])
                let range = NSRange(location: 0, length: input.utf16.count)
    
                var modifiedString = input
                let matches = regex.matches(in: input, options: [], range: range)
                for match in matches.reversed() {
                    if let range = Range(match.range, in: modifiedString) {
                        let matchedString = String(modifiedString[range])
                        let modifiedMatchedString = regex.stringByReplacingMatches(in: matchedString, options: [], range: NSRange(location: 0, length: matchedString.utf16.count), withTemplate: replacement)
                        modifiedString = modifiedString.replacingCharacters(in: range, with: modifiedMatchedString)
                    }
                }
    
                return modifiedString
            } catch {
                print("Error creating regex: (error)")
                return input
            }
        }
    }
    

    Input

    Hello #image(pencil) World! #image(pencil.circle)

    Output

    iPhone 14 Pro Simulator

    I hope you find the answer helpful.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search