0

Happy New Year, all!

I'm trying to migrate my CoreData app to SwiftData. Prior to the migration, the Siri Shortcut's EntityPropertyQuery worked just fine, but now I'm struggling how to combine the [NSPredicate] in the required func entities(matching comparators: [NSPredicate]) with the SwiftData Predicate.

Consider the following:

struct ItemQuery: EntityPropertyQuery {
    
    static var properties = EntityQueryProperties<ItemEntity, NSPredicate> {
        Property(\ItemEntity.$title) {
            EqualToComparator { NSPredicate(format: "title = %@", $0) }
            ContainsComparator { NSPredicate(format: "title CONTAINS %@", $0) }
        }
        Property(\ItemEntity.$date) {
            EqualToComparator { NSCompoundPredicate(type: .and, subpredicates: [
                NSPredicate(format: "date >= %@ AND date <= %@",
                            argumentArray: [
                                Calendar.current.startOfDay(for: $0),
                                Calendar.current.date(byAdding: .minute, value: 1439, to: Calendar.current.startOfDay(for: $0))!
                            ]),
                NSPredicate(format: "date <= %@", Date.now.endOfDay as NSDate)
            ])
            }
        }
    }
    
    static var sortingOptions = SortingOptions {
        SortableBy(\ItemEntity.$title)
        SortableBy(\ItemEntity.$date)
    }
    
    @MainActor
    func suggestedEntities() async throws -> [ItemEntity] {
        let container = DataModel.shared.modelContainer
        let descriptor = FetchDescriptor<Item>(predicate: Item.predicateFor(.previous))
        let results = try? container.mainContext.fetch(descriptor)
        let allEntities = results?.map({ Item in
            ItemEntity(id: Item.id, title: Item.text?.title ?? "")
        })
        return allEntities ?? []
    }
    
    func entities(for identifiers: [ItemEntity.ID]) async throws -> [ItemEntity] {
        try await suggestedEntities().filter{(identifiers.contains($0.id))}
    }
    
    func entities(matching string: String) async throws -> [ItemEntity] {
        try await suggestedEntities().filter { Item in
            Item.title.localizedCaseInsensitiveContains(string)
        }
    }
    
    @MainActor
    func entities(
        matching comparators: [NSPredicate],
        mode: ComparatorMode,
        sortedBy: [Sort<ItemEntity>],
        limit: Int?
    ) async throws -> [ItemEntity] {
        let container = DataModel.shared.modelContainer
        var descriptor = FetchDescriptor<Item>(
            predicate: Item.predicateFor(.previous),
            sortBy: [.init(\.date, order: .reverse)]
        )
        descriptor.fetchLimit = limit ?? 5
        let results = try? container.mainContext.fetch(descriptor)
        
        // How to check/filter based on the NSPredicates?
        
        return ??
    }
}

So the question really boils down to this: is it possible to replace the [NSPredicate type of the comparators parameter with a SwiftData Predicate, or - if it isn't – how do I filter the results using the supplied comparators?

As far as I can tell, EntityPropertyQuery has this associatedtype ComparatorMappingType, but I couldn't find any documentation on what it actually is and how to use it.

Thank you!

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.