I believe I may have found a SwiftData persistence bug, but I'd like to verify that I'm not overlooking a documented limitation before filing Feedback.
This minimal example appears to lose precision when persisting a Decimal:
import Foundation
import SwiftData
@Model
class Item {
var value: Decimal
init(_ value: Decimal) {
self.value = value
}
}
let original = Decimal(string: "123456789012345.6")!
let container = try ModelContainer(
for: Item.self,
configurations: .init(isStoredInMemoryOnly: true)
)
let context = ModelContext(container)
context.insert(Item(original))
try context.save()
let fetched = try ModelContext(container)
.fetch(FetchDescriptor<Item>())
.first!
print(original)
print(fetched.value)
Output:
123456789012345.6
123456789012346
A few observations from additional testing:
Decimal(string:)preserves the value before persistence.Decimal↔NSDecimalNumberbridging preserves the value in separate tests.- The value remains exact after model initialization, insertion, and
save()on the registered object. - The first Swift-visible precision loss appears after fetching from a new
ModelContext. - As a control, I repeated the test using Core Data with an
NSInMemoryStoreTypestore and anNSDecimalAttributeTypeattribute. That round-tripped the tested values exactly. - Inspecting the SQLite store generated by SwiftData showed the affected value stored as a
REAL.
At this point it appears the precision loss occurs somewhere in the SwiftData/Core Data persistence pipeline rather than in Decimal itself.
Can anyone reproduce this, or is there a documented limitation on Decimal persistence in SwiftData that I have missed?
If this is expected behavior, what is the recommended way to persist exact decimal values for financial applications?