In Xcode 15.0.1, I created a new project to start working with SwiftData. I did this by creating a default App project and checking the Use SwiftData checkbox. The resulting project contains just three files: an app entry point file, a ContentView SwiftUI view file, and an Item model file.
The only change I made was to annotate the default Item timestamp property with a .transformable attribute.
Here is the resulting model:
@Model
final class Item {
@Attribute(.transformable(by: TestVT.self)) var timestamp: Date // Only updated this line
init(timestamp: Date) {
self.timestamp = timestamp
}
}
And here is the definition of TestVT. It is a basic ValueTransformer that simply tries to store the Date as a NSNumber:
// Added this
class TestVT: ValueTransformer {
static let name = NSValueTransformerName("TestVT")
override class func transformedValueClass() -> AnyClass {
NSNumber.self
}
override class func allowsReverseTransformation() -> Bool {
true
}
override func transformedValue(_ value: Any?) -> Any? {
guard let date = value as? Date else {
return nil
}
let ti = date.timeIntervalSince1970
return NSNumber(value: ti)
}
override func reverseTransformedValue(_ value: Any?) -> Any? {
guard let num = value as? NSNumber else {
return nil
}
let ti = num.doubleValue as TimeInterval
return Date(timeIntervalSince1970: ti)
}
}
And finally, I made sure to register my ValueTransformer but updating the sharedModelContainer definition in the App:
var sharedModelContainer: ModelContainer = {
ValueTransformer.setValueTransformer(TestVT(), forName: TestVT.name) // Only added this line
let schema = Schema([
Item.self,
])
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
do {
return try ModelContainer(for: schema, configurations: [modelConfiguration])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
}()
Prior to Xcode 15.1, this was working fine. However, now when I try to create an item when running the app I get the following error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for attribute: property = "timestamp"; desired type = NSNumber; given type = __NSTaggedDate; value = 2023-12-14 01:47:11 +0000.'
I'm unsure of why this stopped working. The error seems to be complaining about the input being of type Date when NSNumber was expected, but I thought that's what the ValueTransformer was supposed to be doing.
Important note: prior to Xcode 15.1, I did not originally override the transformedValueClass() and everything was working but in the new Xcode when launching the app I was getting a Thread 1: EXC_BAD_ACCESS (code=1, address=0x0) on the return try ModelContainer(...) line. Removing the .transformable property from my model fixed the issue. That's why I added the override here, because I think the docs indicate overriding it as well and I missed that the first time. This being said, I think the code I have is what a correct ValueTransformer would look like.
If anyone has experienced this issue, or has a working ValueTransformer for SwiftData in Xcode 15.1, please let me know. Appreciate any help with this issue. Thanks so much!