Section 6/181 menit
6. Kueri Data dengan @Query
6. Kueri Data dengan @Query
@Query hanya tersedia di SwiftUI view. Ia secara otomatis mengobservasi perubahan dan me-refresh view.
swift
// Fetch semua books, urutkan by title
struct BookListView: View {
@Query(sort: \Book.title) private var books: [Book]
var body: some View {
List(books) { book in
Text(book.title)
}
}
}
// Fetch dengan filter dan sort
struct UnreadBooksView: View {
@Query(
filter: #Predicate<Book> { !$0.isRead },
sort: [SortDescriptor(\Book.addedAt, order: .reverse)]
)
private var unreadBooks: [Book]
var body: some View {
List(unreadBooks) { book in
BookRowView(book: book)
}
}
}
@Query dengan Parameter Dinamis
Parameter filter di @Query bisa diubah saat runtime dengan cara passing nilai melalui initializer view child:
swift
// Parent view mengontrol filter
struct BookShelfView: View {
@State private var filterByAuthor: String = ""
@State private var showOnlyUnread: Bool = false
var body: some View {
VStack {
FilterControls(
authorFilter: $filterByAuthor,
showUnread: $showOnlyUnread
)
FilteredBookList(
authorFilter: filterByAuthor,
showOnlyUnread: showOnlyUnread
)
}
}
}
// Child view dengan @Query dinamis
struct FilteredBookList: View {
@Query private var books: [Book]
init(authorFilter: String, showOnlyUnread: Bool) {
let predicate = #Predicate<Book> { book in
(authorFilter.isEmpty || book.author.localizedStandardContains(authorFilter))
&& (!showOnlyUnread || !book.isRead)
}
_books = Query(filter: predicate, sort: \Book.title)
}
var body: some View {
List(books) { book in
BookRowView(book: book)
}
}
}
FetchDescriptor untuk Fetch Manual
Di luar SwiftUI (UIKit, background tasks), gunakan FetchDescriptor bersama ModelContext.fetch():
swift
// Fetch dengan limit dan offset (pagination)
var descriptor = FetchDescriptor<Book>()
descriptor.fetchLimit = 20
descriptor.fetchOffset = page * 20
descriptor.sortBy = [SortDescriptor(\Book.publishedYear, order: .reverse)]
let pagedBooks = try context.fetch(descriptor)
// Count tanpa fetch semua object
let totalCount = try context.fetchCount(FetchDescriptor<Book>())
// Fetch hanya IDs (ringan untuk lazy loading)
descriptor.includePendingChanges = false
let ids = try context.fetchIdentifiers(descriptor)