【问题标题】:How to make NSAttributedString codable compliant?如何使 NSAttributedString 可编码兼容?
【发布时间】:2019-06-05 01:40:27
【问题描述】:

有什么问题?

目前我正在我的主应用程序上构建一个应用程序扩展,它通过 JSON 进行通信。主题和数据位于 JSON 中,并通过 Apple 的可编码协议进行解析。我现在遇到的问题是使 NSAttributedString 可编码兼容。我知道它不是内置的,但我知道它可以转换为数据并返回到

到目前为止我有什么?

将 NSAttributedString 强制转换为数据,以便通过 JSON 共享。

if let attributedText = something.attributedText {
    do {
        let htmlData = try attributedText.data(from: NSRange(location: 0, length: attributedText.length), documentAttributes: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType])
        let htmlString = String(data: htmlData, encoding: .utf8) ?? "" 
    } catch {
        print(error)
    }
}

将 html JSON 字符串转换回 NSAttributedString:

do {
    return try NSAttributedString(data: self, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)
} catch {
    print("error:", error)
    return  nil
}

我的问题?

如何制作具有 NSAttributedString 类型的属性 nsAttributedTitle 的结构,并使其可编码以符合自定义编码器解码器?

结构示例(不考虑可编码合规性):

struct attributedTitle: Codable {
    var title: NSAttributedString

    enum CodingKeys: String, CodingKey {
        case title
    }

    public func encode(to encoder: Encoder) throws {}
    public init(from decoder: Decoder) throws {}
}

【问题讨论】:

    标签: nsattributedstring swift codable


    【解决方案1】:

    NSAttributedString 符合 NSCoding,因此您可以使用 NSKeyedArchiver 获取 Data 对象。

    这是一个可能的解决方案

    class AttributedString : Codable {
    
        let attributedString : NSAttributedString
    
        init(nsAttributedString : NSAttributedString) {
            self.attributedString = nsAttributedString
        }
    
        public required init(from decoder: Decoder) throws {
            let singleContainer = try decoder.singleValueContainer()
            guard let attributedString = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(singleContainer.decode(Data.self)) as? NSAttributedString else {
                throw DecodingError.dataCorruptedError(in: singleContainer, debugDescription: "Data is corrupted")
            }
            self.attributedString = attributedString
        }
    
        public func encode(to encoder: Encoder) throws {
            var singleContainer = encoder.singleValueContainer()
            try singleContainer.encode(NSKeyedArchiver.archivedData(withRootObject: attributedString, requiringSecureCoding: false))
        }
    }
    

    【讨论】:

    • 有道理,但我们最终得到了一个类而不是结构。这有一些影响。
    • 你也可以使用结构体。然后你必须删除required
    • 我今晚试试,会尽快接受你的答复。
    • Data 符合 Encodable & Decodable。无需自己编码为base64 stackoverflow.com/questions/58976895/…
    • public required init(from decoder: Decoder) throws { let singleContainer = try decoder.singleValueContainer() guard let attributedString = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(singleContainer.decode(Data.self)) as? NSAttributedString else { throw DecodingError.dataCorruptedError(in: singleContainer, debugDescription: "Data is corrupted") } self.attributedString = attributedString }
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-18
    • 2016-10-25
    • 2010-10-14
    • 1970-01-01
    相关资源
    最近更新 更多