I have been trying so many ways to resolve this issue. I am trying to fetch SwiftData records with a predicate. but everything I try results in a pair of errors:
initializer 'init(_:)' requires that 'Item' conform to 'Encodable'
initializer 'init(_:)' requires that 'Item' conform to 'Decodable'
The error is coming from within the expanded #Predicate
macro.
Here is a bare bones class to demonstrate the issue:
@Model
final class Item {
@Attribute(.unique) var id: String
var timestamp: Date
init(timestamp: Date) {
self.id = UUID().uuidString
self.timestamp = timestamp
}
}
And here is the bare bones code that causes the compiler issue:
extension Item {
static func foo() {
let item = Item(timestamp: .now)
let pred = #Predicate<Item> { $0.id == item.id }
}
}
I've tried so many ways to resolve this error. None of the Apple SwiftData sample projects I've seen give this error.
I've tried conforming to Identifiable
. I've renamed the id
property. I've changed the id
type to UUID
directly instead of String
.
And of course I've added code to conform to Codable
. While that fixed the compiler error, I ended up getting a runtime error. Note that none of the Apple SwiftData projects conform their models to Codable
.
What am I missing?
The solution is to avoid referencing a model object inside the #Predicate
closure.
Simply change the predicate line from:
let pred = #Predicate<Item> { $0.id == item.id }
to:
let anID = item.id
let pred = #Predicate<Item> { $0.id == anID }
While the solution seems trivial and obvious, the error can easily lead you down many wrong paths.