@FetchRequest sa SwiftUI — ano ito, pagkuha ng Core Data at mekanismo

May-akda: IT Sectr Nai-publish: 2026-06-25 Oras ng pagbabasa: 8 min

@FetchRequest sa SwiftUI — property wrapper para sa awtomatikong pagkuha ng data mula sa Core Data na may reaktibong pag-update ng interface. Ang wrapper ay tumatanggap ng NSFetchRequest na may mga predicate ng filter at pag-uuri, at ang resulta — isang NSManagedObject array — ay awtomatikong na-update sa anumang pagbabago sa konteksto ng Core Data. Ayon sa Apple Developer Documentation (2025), ang @FetchRequest ay nangangailangan ng managedObjectContext sa kapaligiran ng SwiftUI at sumusuporta sa mga dynamic na predicate, na nagbibigay ng reaktibong koneksyon sa pagitan ng Core Data at interface ng gumagamit.

Mga pangunahing punto

  • @FetchRequest — property wrapper para sa reaktibong pagkuha ng Core Data sa SwiftUI
  • Awtomatikong pag-update ng UI sa pagdaragdag, pagtanggal, o pagbabago ng mga record sa Core Data
  • Mga predicate at pag-uuri ay itinakda sa initializer o sa pamamagitan ng mga parameter ng property wrapper
  • managedObjectContext ay dapat na available sa pamamagitan ng @Environment sa hierarchy ng View
  • Mga dynamic na predicate ay nagpapahintulot sa pagbabago ng mga kondisyon ng filter sa runtime

Ano ang @FetchRequest sa SwiftUI?

@FetchRequest — ay isang SwiftUI property wrapper na lumilikha at namamahala ng FetchRequest mula sa Core Data. Sa pagsisimula, ang wrapper ay tumatanggap ng uri ng entity, isang NSSortDescriptor array para sa pag-uuri, at isang opsyonal na NSPredicate para sa pag-filter. Ang resulta ay nakaimbak bilang isang array ng mga bagay ng tinukoy na uri ng NSManagedObject at awtomatikong na-update sa mga pagbabago sa layer ng persistensya.

Ang pangunahing tampok ng @FetchRequest ay reaktibidad. Kapag nagbago ang data sa Core Data (save, insert, delete, update), awtomatikong nagsasagawa ng muling pagkuha ang SwiftUI at muling iginuhit ang lahat ng View na gumagamit ng fetch request na ito. Ang developer ay hindi kailangang manu-manong tumawag ng refresh, mag-subscribe sa NSManagedObjectContextDidSaveNotification, o mag-reload ng data. SwiftUI ang namamahala sa buong cycle ng synchronization.

Para gumana ang @FetchRequest, kinakailangan ang NSManagedObjectContext na available sa kapaligiran ng SwiftUI sa pamamagitan ng @Environment(\.managedObjectContext). Ang konteksto ay karaniwang ipinapasa mula sa ugat ng application kung saan nilikha ang NSPersistentContainer. Ang karaniwang pattern — paggamit ng ViewModel o App structure para i-configure ang Core Data stack at ipasa ang konteksto sa pamamagitan ng .environment() modifier.

Pag-uuri at mga predicate ng FetchRequest

Ang @FetchRequest ay tumatanggap ng ilang parameter para i-configure ang pagkuha. SortDescriptors — isang NSSortDescriptor array na tumutukoy sa pagkakasunud-sunod ng mga record. Predicate — NSPredicate para sa pag-filter, halimbawa, pagkuha lamang ng mga gawain na may status na “natapos”. Animation — animation para sa pag-update ng listahan sa mga pagbabago ng data.

Ang mga predicate ng Core Data ay gumagamit ng format ng expression na katulad ng SQL: NSPredicate(format: “status == %@”, “completed”). Maraming kondisyon ang maaaring pagsamahin sa pamamagitan ng AND, OR at NOT. SortDescriptors ay tumutukoy sa pagkakasunud-sunod: NSSortDescriptor(keyPath: \Task.dueDate, ascending: true). Para sa pag-uuri sa maraming field, isang array ng mga descriptor ang ipinapasa — ang una ay inilalapat bilang pangunahing, ang natitira bilang pangalawa.

swift
struct TaskListView: View {
    @Environment(\.managedObjectContext) var viewContext

    @FetchRequest(
        sortDescriptors: [
            NSSortDescriptor(keyPath: \.Task.dueDate, ascending: true),
            NSSortDescriptor(keyPath: \.Task.priority, ascending: false)
        ],
        predicate: NSPredicate(format: "isCompleted == NO"),
        animation: .default
    )
    var tasks: FetchedResults<Task>

    var body: some View {
        List(tasks) { task in
            Text(task.title ?? "")
        }
    }
}

Sa halimbawa, ang @FetchRequest ay pumipili ng lahat ng hindi natapos na gawain (isCompleted == NO), unang inayos ayon sa petsa (pataas), pagkatapos ay ayon sa priyoridad (pababa). FetchedResults<Task> — isang awtomatikong na-update na koleksyon na kumikilos tulad ng isang array para sa ForEach at List. Ang .default animation ay nagsisiguro ng maayos na paglitaw/paglaho ng mga record sa mga pagbabago.

@FetchRequest na may List at dynamic na data

@FetchRequest ay perpektong pinagsama sa List at ForEach para sa pagpapakita ng mga dynamic na listahan ng Core Data. Ang resulta ng pagkuha (FetchedResults) ay tumutugma sa RandomAccessCollection protocol, kaya maaari itong gamitin nang direkta sa List at ForEach. Sa pagdaragdag, pagtanggal, o pagbabago ng mga record, ang listahan ay awtomatikong iginuhit muli na may animation.

Para sa pagtanggal ng mga record, ginagamit ang delete na paraan ng konteksto. Para sa pagdaragdag — paglikha ng bagong NSManagedObject at pagtawag ng save. Lahat ng pagbabago ay ginagawa sa pamamagitan ng viewContext, na kasama ng @FetchRequest ay nagsisiguro ng consistency ng data. Para sa pag-edit, ginagamit ang @ObservedObject o @Bindable para sa isang partikular na Core Data object.

swift
struct TaskListWithActions: View {
    @Environment(\.managedObjectContext) var viewContext

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \.Task.createdAt,
                                               ascending: false)]
    )
    var tasks: FetchedResults<Task>

    var body: some View {
        List {
            ForEach(tasks) { task in
                HStack {
                    Text(task.title ?? "")
                    Spacer()
                    Image(systemName: task.isCompleted
                               ? "checkmark.circle.fill"
                               : "circle")
                }
                .onTapGesture { toggleTask(task) }
            }
            .onDelete(perform: deleteTasks)
        }
        .toolbar {
            Button(systemImage: "idagdag") { addTask() }
        }
    }

    private func addTask() {
        let newTask = Task(context: viewContext)
        newTask.title = "New task \(tasks.count + 1)"
        newTask.createdAt = Date()
        try? viewContext.save()
    }

    private func toggleTask(_ task: Task) {
        task.isCompleted.toggle()
        try? viewContext.save()
    }

    private func deleteTasks(at offsets: IndexSet) {
        for index in offsets {
            viewContext.delete(tasks[index])
        }
        try? viewContext.save()
    }
}

Ang halimbawang ito ay nagpapakita ng kumpletong CRUD na may @FetchRequest. Pagdaragdag: paglikha ng Task sa pamamagitan ng konteksto at save(). Pagtanggal: delete() sa konteksto at save(). Pag-update: toggle ng property at save(). Pagkatapos ng bawat save(), ang @FetchRequest ay awtomatikong muling humihiling ng data, at ang List ay na-update na may animation. Ang mga modifier na onDelete at onTapGesture ay nagbibigay ng mga karaniwang iOS na interaksyon.

Mga dynamic na predicate sa runtime

Ang @FetchRequest ay sumusuporta sa mga dynamic na predicate sa pamamagitan ng parameter na predicate na maaaring baguhin sa runtime. Para dito, kailangan mong lumikha ng @FetchRequest na may variable-predicate at ipasa ito sa pamamagitan ng Binding. Kapag binago ng gumagamit ang filter — halimbawa, pumili ng kategorya ng gawain — ang predicate ay na-update, at ang pagkuha ay awtomatikong muling sisimulan.

Ang mga dynamic na predicate ay ipinapatupad sa pamamagitan ng @State o @Published property, na ipinapasa bilang Binding sa initializer ng @FetchRequest. Sinusubaybayan ng SwiftUI ang pagbabago ng Binding na ito at muling lumikha ng NSFetchRequest na may bagong predicate, awtomatikong ina-update ang listahan.

Mga halimbawa ng code @FetchRequest

Tingnan natin ang isang kumpletong halimbawa ng application ng journal na may @FetchRequest para sa pagkuha ng mga tala. Ang form ng paghahanap ay gumagamit ng dynamic na predicate: kapag naglalagay ng teksto, awtomatikong ina-update ng FetchRequest ang mga resulta, na nag-filter ng mga tala ayon sa pamagat at nilalaman. Pag-uuri — ayon sa petsa ng paglikha, mula bago hanggang luma.

swift
struct JournalEntryView: View {
    @Environment(\.managedObjectContext) var viewContext
    @State private var searchText = ""

    private var searchPredicate: NSPredicate? {
        guard !searchText.isEmpty else { return nil }
        return NSPredicate(format: "title CONTAINS[c] %@", searchText)
    }

    @FetchRequest var entries: FetchedResults<JournalEntry>

    init(searchText: String) {
        let sort = [NSSortDescriptor(keyPath: \.JournalEntry.date,
                                           ascending: false)]
        let pred: NSPredicate? = searchText.isEmpty
            ? nil
            : NSPredicate(format: "title CONTAINS[c] %@ OR content CONTAINS[c] %@",
                          searchText, searchText)
        self._entries = FetchRequest(
            sortDescriptors: sort,
            predicate: pred,
            animation: .default
        )
    }

    var body: some View {
        List(entries) { entry in
            VStack(alignment: .leading) {
                Text(entry.title ?? "").font(.headline)
                Text(entry.content ?? "").font(.subheadline)
                    .lineLimit(2)
            }
        }
        .searchable(text: $searchText)
    }
}

Talaan ng journal na may paghahanap: kapag naglalagay ng teksto sa searchable field, ang NSPredicate na may CONTAINS[c] (paghahanap na hindi sensitibo sa malaki/maliit na titik) ay nilikha sa mga field na title at content. Tinatanggap ng Init ang searchText at lumilikha ng FetchRequest na may kaukulang predicate. Awtomatikong ina-update ng Searchable modifier ang searchText, at ang @FetchRequest ay tumutugon sa pagbabago ng predicate at muling humihiling ng data.

Para sa mas kumplikadong mga senaryo na may maraming filter, pagsamahin ang NSCompoundPredicate sa AND/OR logic. Sinusuportahan ng @FetchRequest ang mga predicate ng anumang kumplikado, kabilang ang mga nested subquery (SUBQUERY) para sa pag-filter ayon sa mga relasyon. Gayunpaman, tandaan: ang mga kumplikadong predicate ay nakakaapekto sa pagganap — para sa malalaking dataset (higit sa 10,000 record) gamitin ang Core Data indexing at limitahan ang pagkuha sa pamamagitan ng fetchLimit.

Mga madalas itanong

Paano ipasa ang managedObjectContext sa @FetchRequest?

Magdagdag ng @Environment(\.managedObjectContext) var viewContext sa root View at ipasa ito sa pamamagitan ng .environment(\.managedObjectContext, context) modifier. Lahat ng child View na gumagamit ng @FetchRequest ay awtomatikong makakakuha ng konteksto mula sa kapaligiran.

Maaari bang ma-update ang @FetchRequest nang hindi ni-reload ang View?

Oo, baguhin ang konteksto ng Core Data: magdagdag, magtanggal, o mag-update ng object at tawagan ang save(). Awtomatikong magsasagawa ng muling pagkuha ang @FetchRequest at ia-update ang UI. Para sa sapilitang pag-update nang walang save() gamitin ang viewContext.refreshAllObjects().

Ano ang pagkakaiba sa pagitan ng @FetchRequest at @SectionedFetchRequest?

Ang @FetchRequest ay nagbabalik ng flat array ng mga bagay. Ang @SectionedFetchRequest ay nag-grupo ng mga resulta ayon sa tinukoy na key path sa mga seksyon, katulad ng UITableView na may sectionNameKeyPath. Gamitin ang @SectionedFetchRequest para sa mga naka-grupong listahan na may mga pamagat ng seksyon.

Paano gamitin ang @FetchRequest sa Relationship?

Para sa pag-filter ayon sa mga relasyon, gamitin ang dot notation: NSPredicate(format: “category.name == %@”, “Work”). Awtomatikong nagsasagawa ng JOIN ang @FetchRequest sa SQLite. Para sa pag-access sa relasyon sa pamamagitan ng napiling object, gamitin ang mga ordinaryong NSManagedObject property.

Sinusuportahan ba ng @FetchRequest ang pagination?

Hindi direktang sinusuportahan ng @FetchRequest ang pagination, dahil ito ay idinisenyo para sa pagpapakita ng lahat ng record na may reaktibong pag-update. Para sa pagination, gamitin ang NSFetchRequest na may fetchLimit/fetchOffset at manu-manong mag-load ng data habang nag-i-scroll ng listahan.

Buod

  • @FetchRequest — property wrapper para sa awtomatikong reaktibong pagkuha ng Core Data sa SwiftUI
  • Pag-uuri itinakda sa NSSortDescriptor array, pag-filter — sa NSPredicate
  • Awtomatikong pag-update ng UI sa bawat pagbabago ng data sa konteksto ng Core Data
  • managedObjectContext ipinapasa sa pamamagitan ng @Environment sa hierarchy ng View
  • Mga dynamic na predicate ipinapatupad sa pamamagitan ng custom init na may parameter na predicate
  • Mga operasyon ng CRUD ginagawa sa pamamagitan ng viewContext na may awtomatikong synchronization ng listahan
  • Gamitin ang @FetchRequest para sa pagpapakita ng Core Data, @SectionedFetchRequest — para sa mga naka-grupong listahan

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din