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!