Thanks for the fast answer, but I think I'm still missing something.
I now created my own struct like this:
struct MyModel: Codable, Hashable {
@CodableConfiguration(from: \.myApp) var attrStr: AttributedString = AttributedString()
}
And continued with:
enum MyModelTextAttribute: CodableAttributedStringKey {
typealias Value = MyModel
static let name = "myModelTextAttribute"
}
extension AttributeScopes {
struct MyAppAttributes: AttributeScope {
let myModelTextAttribute: MyModelTextAttribute
let swiftUI: SwiftUIAttributes
}
var myApp: MyAppAttributes.Type { MyAppAttributes.self }
}
extension AttributeDynamicLookup {
subscript<T: AttributedStringKey>(dynamicMember keyPath: KeyPath<AttributeScopes.MyAppAttributes, T>) -> T { self[T.self] }
}
The JSON decoding of the model works fine:
let model = MyModel(attrStr: AttributedString("Hi"))
let json = try JSONEncoder().encode(model)
print(String(data: json, encoding: .utf8) ?? "no data")
// prints: {"attrStr":"Hi"}
So I created an attributed string and set the attributes:
var attStr = AttributedString("Hello, here is some text.")
let range1 = attStr.range(of: "Hello")!
let range2 = attStr.range(of: "text")!
attStr[range1].myModelTextAttribute = model
attStr[range2].foregroundColor = .blue
Printing the attributed string with print(attStr) looks also fine:
Hello {
myModelTextAttribute = MyModel(_attrStr: Foundation.CodableConfiguration<Foundation.AttributedString, (extension in __lldb_expr_87):Foundation.AttributeScopes.MyAppAttributes>(wrappedValue: Hi {
}))
}
, here is some {
}
text {
SwiftUI.ForegroundColor = blue
}
. {
}
But if I now try to convert it to JSON, my custom attribute is missing:
let jsonData = try JSONEncoder().encode(attStr)
print(String(data: jsonData, encoding: .utf8) ?? "no data")
// prints: ["Hello",{},", here is some ",{},"text",{"SwiftUI.ForegroundColor":{}},".",{}]
I also tried option 2 with a custom encode function in MyModel instead, but got the same result. Here is also my implementation for that:
struct MyModel: Codable, Hashable {
var attrStr: AttributedString = AttributedString()
enum MyCodingKey: CodingKey {
case attrStrKey
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: MyCodingKey.self)
try container.encode(attrStr, forKey: .attrStrKey, configuration: AttributeScopes.MyAppAttributes.self)
}
}