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 ↔ NSDecimalNumber bridging 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 NSInMemoryStoreType store and an NSDecimalAttributeType attribute. 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?
0
0
223