Search code examples
swiftpredicateswiftdata

How to resolve compiler error creating a SwiftData #Predicate?


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?


Solution

  • 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.