为包含NSAttributedString的类实现Codable时遇编译错误
嘿,我来帮你搞定这个NSAttributedString实现Codable的问题~
首先咱们先拆解下你遇到的两个错误:
- 编码时的歧义错误:Swift的
encode(_:forKey:)没有直接支持NSAttributedString的重载,因为NSAttributedString本身并没有实现Codable协议,编译器不知道该用哪个编码逻辑,所以抛出了歧义错误。 - 解码时的类型不匹配错误:你尝试解码成
NSMutableAttributedString,但你的属性str是NSAttributedString类型,而且本质上这两个类都没实现Codable,所以没有对应的decode方法能返回你需要的类型。
其实你不用绕弯子转NSData,直接给NSAttributedString扩展Codable协议就行——利用它本身支持的NSCoding能力,通过归档/解归档来实现Codable的编码解码逻辑。
下面是完整的解决方案:
第一步:给NSAttributedString扩展Codable
extension NSAttributedString: Codable { public func encode(to encoder: Encoder) throws { // 把NSAttributedString归档成Data let data = try NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: false) var container = encoder.singleValueContainer() try container.encode(data) } public init(from decoder: Decoder) throws { // 解码出Data,再解归档成NSAttributedString let container = try decoder.singleValueContainer() let data = try container.decode(Data.self) guard let attributedString = try NSKeyedUnarchiver.unarchivedObject(ofClass: NSAttributedString.self, from: data) else { throw DecodingError.dataCorruptedError(in: container, debugDescription: "无法解归档得到NSAttributedString") } self.init(attributedString: attributedString) } }
第二步:修改你的Text类
现在NSAttributedString已经支持Codable了,你的Text类可以直接使用自动合成的Codable实现,当然如果你需要自定义编码解码逻辑,保留原来的代码也完全没问题,现在不会再报错了:
class Text: Codable { var str: NSAttributedString enum CodingKeys: String, CodingKey { case str } // 可选:如果不需要自定义逻辑,这两个方法可以完全删掉,Codable会自动合成 func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(str, forKey: .str) // 现在不会有歧义了 } required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) str = try container.decode(NSAttributedString.self, forKey: .str) // 类型匹配,解码正常 } }
额外说明
如果你需要使用NSMutableAttributedString,可以在扩展时给它也加Codable支持,或者在解码后把NSAttributedString转成可变版本:
// 解码后转可变 let mutableStr = NSMutableAttributedString(attributedString: str)
内容的提问来源于stack exchange,提问作者daven11
相关产品推荐
相关产品推荐

