将NSAttributedString更改为Codable会引发错误 [英] Conforming NSAttributedString to Codable throws error
问题描述
我需要使用以前的
I need write and read NSAttributedString
data into a json file, using this previously answered question I can encode the it but it throws an error while decoding.
class AttributedString : Codable {
let attributedString : NSAttributedString
init(attributedString : NSAttributedString) {
self.attributedString = attributedString
}
public required init(from decoder: Decoder) throws {
let singleContainer = try decoder.singleValueContainer()
let base64String = try singleContainer.decode(String.self)
guard let data = Data(base64Encoded: base64String) else { throw DecodingError.dataCorruptedError(in: singleContainer, debugDescription: "String is not a base64 encoded string") }
guard let attributedString = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSAttributedString.self], from: data) as? NSAttributedString else { throw DecodingError.dataCorruptedError(in: singleContainer, debugDescription: "Data is not NSAttributedString") }
self.attributedString = attributedString
}
func encode(to encoder: Encoder) throws {
let data = try NSKeyedArchiver.archivedData(withRootObject: attributedString, requiringSecureCoding: false)
var singleContainer = encoder.singleValueContainer()
try singleContainer.encode(data.base64EncodedString())
}
}
并且:
do {
let jsonEncoder = JSONEncoder()
let jsonData = try jsonEncoder.encode(attributedString)
let jsonString = String(data: jsonData, encoding: .utf8)
print("***\n\(String(describing: jsonString))\n***") // It works
let jsonDecoder = JSONDecoder()
let attrib = try jsonDecoder.decode(AttributedString.self, from: jsonData)
print(attrib.attributedString.string)
}catch{
print(error) // throws error
}
错误域= NSCocoaErrorDomain代码= 4864键'NS.objects'
的值属于意外类'NSShadow'。允许的类是'{(
NSGlyphInfo,
UIColor,
NSDictionary,
UIFont,
NSURL,
NSParagraphStyle,
NSString,
NSAttributedString,
NSArray,
NSNumber}}'。 UserInfo = {NSDebugDescription =键'NS.objects'的值属于意外类'NSShadow'。允许的类为
'{ (
NSGlyphInfo,
UIColor,
NSDictionary,
UIFont,
NSURL,
NSParagraphStyle,
NSString,
NSAttributedString,
NSArray,
NSNumber)}'。}
Error Domain=NSCocoaErrorDomain Code=4864 "value for key 'NS.objects' was of unexpected class 'NSShadow'. Allowed classes are '{( NSGlyphInfo, UIColor, NSDictionary, UIFont, NSURL, NSParagraphStyle, NSString, NSAttributedString, NSArray, NSNumber )}'." UserInfo={NSDebugDescription=value for key 'NS.objects' was of unexpected class 'NSShadow'. Allowed classes are '{( NSGlyphInfo, UIColor, NSDictionary, UIFont, NSURL, NSParagraphStyle, NSString, NSAttributedString, NSArray, NSNumber )}'.}
PS:保留属性
推荐答案
您可以尝试 unarchiveTopLevelObjectWithData
取消存档AttributedString对象数据:
You can try unarchiveTopLevelObjectWithData
to unarchive your AttributedString object data:
NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data)
您的 AttributedString
我作为结构体实现的应该看起来像这样:
Your AttributedString
implemented as a struct should look something like this:
struct AttributedString {
let attributedString: NSAttributedString
init(attributedString: NSAttributedString) { self.attributedString = attributedString }
init(string str: String, attributes attrs: [NSAttributedString.Key: Any]? = nil) { attributedString = .init(string: str, attributes: attrs) }
}
< hr>
存档/编码
extension NSAttributedString {
func data() throws -> Data { try NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: false) }
}
extension AttributedString: Encodable {
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(attributedString.data())
}
}
取消存档/解码
extension Data {
func topLevelObject() throws -> Any? { try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(self) }
func unarchive<T>() throws -> T? { try topLevelObject() as? T }
func attributedString() throws -> NSAttributedString? { try unarchive() }
}
extension AttributedString: Decodable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
guard let attributedString = try container.decode(Data.self).attributedString() else {
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Corrupted Data")
}
self.attributedString = attributedString
}
}
这篇关于将NSAttributedString更改为Codable会引发错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!