admin管理员组

文章数量:1405141

I saw a wwdc video and write custom extension to make an AttributedString. Everything seems to be ok to me but I can't make the image it appear. Can you tell me what is wrong?

public extension String {
    func skinned() -> AttributedString {
        var output = attributed(scope: AttributeScopes.CustomAttributes.self)

        for run in output.runs {
            if let imageStyle = run.customAttributes.imageStyle {
                switch imageStyle {
                case .trash:
                    output[run.range].attachment =
                        .init(image: UIImage(systemName: "trash")!)
                }
            }
        }

        return output
    }
}

enum ImageAttributes: CodableAttributedStringKey, MarkdownDecodableAttributedStringKey {
    static let name = "image"

    enum Value: String, Codable, Sendable {
        case trash
    }
}

extension AttributeScopes {
    struct CustomAttributes: AttributeScope {
        let imageStyle: ImageAttributes
    }

    var customAttributes: CustomAttributes.Type  { CustomAttributes.self }
}

#Preview {
    Text("Put it in the ^[trash](image: 'trash')!".skinned())

    // Text("Let’s see this \(Image(systemName: "trash"))!") // Something like this but with using the markdown format instead
}

I saw a wwdc video and write custom extension to make an AttributedString. Everything seems to be ok to me but I can't make the image it appear. Can you tell me what is wrong?

public extension String {
    func skinned() -> AttributedString {
        var output = attributed(scope: AttributeScopes.CustomAttributes.self)

        for run in output.runs {
            if let imageStyle = run.customAttributes.imageStyle {
                switch imageStyle {
                case .trash:
                    output[run.range].attachment =
                        .init(image: UIImage(systemName: "trash")!)
                }
            }
        }

        return output
    }
}

enum ImageAttributes: CodableAttributedStringKey, MarkdownDecodableAttributedStringKey {
    static let name = "image"

    enum Value: String, Codable, Sendable {
        case trash
    }
}

extension AttributeScopes {
    struct CustomAttributes: AttributeScope {
        let imageStyle: ImageAttributes
    }

    var customAttributes: CustomAttributes.Type  { CustomAttributes.self }
}

#Preview {
    Text("Put it in the ^[trash](image: 'trash')!".skinned())

    // Text("Let’s see this \(Image(systemName: "trash"))!") // Something like this but with using the markdown format instead
}
Share Improve this question edited Mar 8 at 21:26 Trajanos asked Mar 8 at 16:33 TrajanosTrajanos 2333 silver badges16 bronze badges 1
  • You may want to link to the respective WWDC video as context and reference for others and maybe also provide some insight as to what you're trying to achieve, in case there may be solutions other than AttributedString that use markdown format. – Andrei G. Commented Mar 8 at 20:26
Add a comment  | 

1 Answer 1

Reset to default 1

The SwiftUI attribute scope does not support the attachment attribute. AttributedStrings produced this way cannot be displayed correctly by SwiftUI Text. A UILabel can display this correctly. See my answer here for how to write a UIViewRepresentable for UILabel.

If you don't specifically need an AttributedString, you can convert the markdown string to a Text by concatenating each run. When you encounter your custom markdown tag, use the Text initialiser that takes an Image.

public extension String {
    func attributedText() -> Text {
        var output = Text("")
        let parsedMarkdown = try! AttributedString(markdown: self, including: AttributeScopes.CustomAttributes.self)

        for run in parsedMarkdown.runs {
            if let imageStyle = run.customAttributes.imageStyle {
                switch imageStyle {
                case .trash:
                    output = output + Text(Image(systemName: "trash"))
                }
            } else {
                output = output + Text(AttributedString(parsedMarkdown[run.range]))
            }
        }

        return output
    }
}

#Preview {
    "Put it in the ^[trash](image: 'trash')!".attributedText()
}

本文标签: How to add image to AttributedString to use in SwiftUI using custom markdown formatStack Overflow