You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 01:03:13