Section 6/181 menit
6. EntityQuery: Resolusi Entitas dari Shortcuts
6. EntityQuery: Resolusi Entitas dari Shortcuts
EntityQuery mendefinisikan bagaimana sistem menemukan dan memfilter entities ketika user memilih parameter di Shortcuts atau Siri.
Basic EntityQuery
swift
struct TaskEntityQuery: EntityQuery {
// Lookup by ID — dipanggil saat Shortcuts me-restore saved workflow
func entities(for identifiers: [UUID]) async throws -> [TaskEntity] {
let tasks = try await TaskRepository.shared.fetch(ids: identifiers)
return tasks.map { TaskEntity(task: $0) }
}
// Semua entities untuk picker — dipanggil saat user tap parameter di Shortcuts
func suggestedEntities() async throws -> [TaskEntity] {
let tasks = try await TaskRepository.shared.fetchAll()
return tasks.map { TaskEntity(task: $0) }
}
}
EnumerableEntityQuery: Untuk Dataset Kecil yang Bisa Diambil Sekaligus
swift
struct TagEntityQuery: EnumerableEntityQuery {
// Semua entities sekaligus — cocok untuk dataset <100 item
func allEntities() async throws -> [TagEntity] {
let tags = try await TagRepository.shared.fetchAll()
return tags.map { TagEntity(tag: $0) }
}
}
EntityStringQuery: Dengan Search Support
swift
struct ContactEntityQuery: EntityQuery, EntityStringQuery {
func entities(for identifiers: [String]) async throws -> [ContactEntity] {
return try await ContactService.shared.fetch(ids: identifiers)
.map { ContactEntity(contact: $0) }
}
func suggestedEntities() async throws -> [ContactEntity] {
// Tampilkan recent contacts sebagai suggestion
let recentContacts = try await ContactService.shared.fetchRecent(limit: 10)
return recentContacts.map { ContactEntity(contact: $0) }
}
// Search saat user ketik di Shortcuts parameter picker
func entities(matching string: String) async throws -> [ContactEntity] {
let results = try await ContactService.shared.search(query: string)
return results.map { ContactEntity(contact: $0) }
}
}
EntityPropertyQuery: Filter Canggih
swift
// Memungkinkan user filter entities berdasarkan property (seperti Shortcuts "Filter" block)
struct TaskEntityQuery: EntityQuery, EntityPropertyQuery {
// Definisi property yang bisa difilter
static var properties = EntityQueryProperties<TaskEntity, NSPredicate> {
Property(\TaskEntity.$title) {
EqualToComparator { NSPredicate(format: "title == %@", $0) }
ContainsComparator { NSPredicate(format: "title CONTAINS[cd] %@", $0) }
}
Property(\TaskEntity.$isCompleted) {
EqualToComparator { NSPredicate(format: "isCompleted == %@", NSNumber(value: $0)) }
}
Property(\TaskEntity.$priority) {
EqualToComparator { NSPredicate(format: "priority == %@", $0.rawValue) }
}
}
// Definisi sort options yang tersedia
static var sortingOptions = SortingOptions {
SortableBy(\TaskEntity.$title)
SortableBy(\TaskEntity.$dueDate)
}
func entities(
matching comparators: [NSPredicate],
mode: ComparatorMode,
sortedBy: [Sort<TaskEntity>],
limit: Int?
) async throws -> [TaskEntity] {
let compound = mode == .and
? NSCompoundPredicate(andPredicateWithSubpredicates: comparators)
: NSCompoundPredicate(orPredicateWithSubpredicates: comparators)
return try await TaskRepository.shared.fetch(
predicate: compound,
sortDescriptors: sortedBy.map { $0.nsSortDescriptor },
limit: limit
).map { TaskEntity(task: $0) }
}
func entities(for identifiers: [UUID]) async throws -> [TaskEntity] {
try await TaskRepository.shared.fetch(ids: identifiers).map { TaskEntity(task: $0) }
}
func suggestedEntities() async throws -> [TaskEntity] {
try await TaskRepository.shared.fetchPending().map { TaskEntity(task: $0) }
}
}