Swift 5.5 introduced AttributedString
conforming to Codable
however this is not working for me as I’d expect.
Take the following example:
Here I define a custom attribute TextCase
public enum TextCase: Codable {
case lowercase
case uppercase
}
public struct TextCaseAttribute: CodableAttributedStringKey {
public typealias Value = TextCase
public static var name = "TextCaseAttribute"
}
public extension AttributeScopes {
struct ExtendedTextAttributes: AttributeScope {
public let textCase: TextCaseAttribute
public let foundation: FoundationAttributes
}
var customAttributes: ExtendedTextAttributes.Type { ExtendedTextAttributes.self }
}
public extension AttributeDynamicLookup {
subscript<T: AttributedStringKey>(
dynamicMember keyPath: KeyPath<AttributeScopes.ExtendedTextAttributes, T>
) -> T {
get { self[T.self] }
}
}
and use it like this:
var hello: AttributedString {
var result = AttributedString("Hello")
result.textCase = .uppercase
result.font = .largeTitle
return result
}
when I use JSONEncoder to encode the AttributedString
it gives me the following:
po String(decoding: JSONEncoder().encode(hello), as: UTF8.self)
->
"["Hello",{"SwiftUI.Font":{}}]"
Notice that my textCase
is missing plus I expected SwiftUI.Font
to have a value.
2
Answers
Implementing custom encoding and decoding seems to work:
print it like this
Source: Apple
swift-corelibs-foundation
test code here https://github.com/apple/swift-corelibs-foundation/blob/main/Tests/Foundation/Tests/TestAttributedString.swiftstill curious why encoding a Codable type won't work.
This solution is for NSAttributedString but you can convert it to AttributedString with init function:
https://developer.apple.com/forums/thread/682431
You can packing the NSAttributedString in a Codable container, and the container is Data: you can convert the NSAttributedString to Data. Because Data is codable so your custom Struct will able to be codable:
Code to convert NSAttributedString to Data:
Code to convert Data back to NSAttributedString:
Add it to your custom Struct and make the whole struct Codable:
Pack it in a computedVariable for better syntax: