Search code examples
swiftuiswiftdata

SwiftData @Query with #Predicate on Relationship Model


XCode 15 beta 6.

Just want to do a very simple Query Predicate where the relationship model matches:

@Query(
    filter: #Predicate<Piece> {
        $0.artist == selectedArtist
    },
    sort: [
        SortDescriptor(\Piece.age, order: .reverse)
    ]
) var pieces: [Piece]

and I'm receiving error:

Cannot convert value of type 'PredicateExpressions.Equal<PredicateExpressions.KeyPath<PredicateExpressions.Variable, Artist>, PredicateExpressions.Value>' to closure result type 'any StandardPredicateExpression'

I also tried .id and .persistentModelId on the artist but no luck.

This seems like the most basic predicate use case so I'd be shocked if it's not supported. Any ideas what i'm missing?

My models are basic:

@Model
final class Piece {
    var age: Int
    var artist: Artist
}

And

@Model
final class Artist {
    var name: String
    
    @Relationship(
        deleteRule: .cascade, 
        inverse: \Piece.artist
    )
    var pieces: [Piece]?
}

Solution

  • Per answer here, it seems like #Predicate will not let you use another @Model in the code block. Based on this logic, I don't think there's a way to do this as part of @Query without jumping through a bunch of hoops.

    If your dataset is relatively small, the best suggestion is to filter it yourself:

    @Query(
        sort: [
            SortDescriptor(\Piece.age, order: .reverse)
        ]
    ) var pieces: [Piece]
    
    private var filteredPieces: [Piece] {
        return pieces.compactMap { piece in
            guard let artist = piece.artist else {
                return nil
            }
            return artist == selectedArtist ? piece : nil
        }
    }
    

    and you can use your filtered data below:

    var body: some View {
        List {
            ForEach(filteredPieces) { piece in
                //show filtered stuff
            }
        }
    }