SwiftData Predicates and .contains(where: )

Hi,

I have the following predicate used in a SwiftData Query:

#Predicate<Item> {
    searchText.isEmpty || $0.myarray.contains(where: {
        $0.text.localizedStandardContains(searchText)
    })
})

Even though this compiles, I get the unsupportedKeyPath error in the logs:

Query encountered an error: SwiftData.SwiftDataError(_error: SwiftData.SwiftDataError._Error.unsupportedKeyPath)

I thought I could use .contains(where:) inside predicates, but this doesn't work. What could be the problem?

Item.myarray is an array of a Codable struct type, and searchText is a String.

Answered by MartinP7r in 798652022

I'm not exactly sure if this is the same issue, but from what I understand, collections, enums and other non-trivial value types are stored as binary data in CloudKit (you can check in CloudKit console) and their contents therefore can't be queried with a predicate.

It's also mentioned here: https://www.hackingwithswift.com/quick-start/swiftdata/using-structs-and-enums-in-swiftdata-models

Did you try to explicit the second $0 ?

searchText.isEmpty || $0.myarray.contains { item in item.text.localizedStandardContains(searchText) }

@Claude31 Yes, I tried that. I also thought it could be the $0 but it still doesn't work :(

I do have a workaround that I might implement (moving the text in the parent class), but I'm also wondering what could be the problem here.

Could it be related to Item.myarray's type (an array of structs that conform to Codable)?

Accepted Answer

I'm not exactly sure if this is the same issue, but from what I understand, collections, enums and other non-trivial value types are stored as binary data in CloudKit (you can check in CloudKit console) and their contents therefore can't be queried with a predicate.

It's also mentioned here: https://www.hackingwithswift.com/quick-start/swiftdata/using-structs-and-enums-in-swiftdata-models

SwiftData Predicates and .contains(where: )
 
 
Q