如何通过自定义Markdown格式在SwiftUI的AttributedString中添加图片?
问题:自定义AttributedString无法显示图片附件
我观看了WWDC2021的视频后,编写了自定义扩展来创建AttributedString。我觉得代码逻辑没问题,但图片始终无法显示,能不能帮我排查问题?以下是我的代码:
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 }
问题排查与修复方案
1. 自定义属性动态查找未配置
原代码缺少AttributeDynamicLookup扩展,导致run.customAttributes.imageStyle无法正确访问自定义属性,需补充:
extension AttributeDynamicLookup { subscript<T: AttributeKey>(dynamicMember keyPath: KeyPath<AttributeScopes.CustomAttributes, T>) -> T { return self[T.self] } }
2. Markdown解析未注册自定义属性
直接用attributed(scope:)无法让解析器识别自定义属性,需手动创建解析器并注册:
修改skinned()方法:
public extension String { func skinned() -> AttributedString { var parser = MarkdownParser() parser.register(ImageAttributes.self) guard var output = try? parser.parse(self) as AttributedString else { return AttributedString(self) } for run in output.runs { if let imageValue = run[ImageAttributes.self] { switch imageValue { case .trash: if let image = UIImage(systemName: "trash") { output[run.range].attachment = .init(image: image) } } } } return output } }
3. 补充Markdown属性解码逻辑
为ImageAttributes添加解码方法,确保Markdown属性值能正确解析为枚举值:
enum ImageAttributes: CodableAttributedStringKey, MarkdownDecodableAttributedStringKey { static let name = "image" enum Value: String, Codable, Sendable { case trash } static func decode(from decoder: Decoder) throws -> Value { let container = try decoder.singleValueContainer() return try container.decode(Value.self) } }
4. 简化冗余的AttributeScopes配置
移除AttributeScopes中冗余的customAttributes属性,简化为:
extension AttributeScopes { struct CustomAttributes: AttributeScope { let imageStyle: ImageAttributes } }
修复后的代码可正确解析自定义Markdown语法,并将指定文本替换为SF Symbols图片。
内容的提问来源于stack exchange,提问作者Trajanos
相关产品推荐
相关产品推荐

