如何使 NSAttributedString 可编码兼容?
How to make NSAttributedString codable compliant?
有什么问题?
目前我正在我的主应用程序上构建一个应用程序扩展,它通过 JSON 进行通信。主题和数据位于 JSON 中,并通过 Apple 的可编码协议进行解析。我现在遇到的问题是使 NSAttributedString 可编码兼容。我知道它不是内置的,但我知道它可以转换为数据并返回 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
}
我的问题?
How to make a struct that has a property nsAttributedTitle which is of type NSAttributedString and make it codable compliant with custom encoder decoder?
结构示例(不考虑可编码合规性):
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
符合 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))
}
}
有什么问题?
目前我正在我的主应用程序上构建一个应用程序扩展,它通过 JSON 进行通信。主题和数据位于 JSON 中,并通过 Apple 的可编码协议进行解析。我现在遇到的问题是使 NSAttributedString 可编码兼容。我知道它不是内置的,但我知道它可以转换为数据并返回 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
}
我的问题?
How to make a struct that has a property nsAttributedTitle which is of type NSAttributedString and make it codable compliant with custom encoder decoder?
结构示例(不考虑可编码合规性):
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
符合 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))
}
}