SwiftUI में @FetchRequest — यह क्या है, Core Data फ़ेचिंग और तंत्र

लेखक: IT Sectr प्रकाशित: 2026-06-25 पढ़ने का समय: 8 मिनट

SwiftUI में @FetchRequest — Core Data से स्वचालित रूप से डेटा प्राप्त करने के लिए एक property wrapper जिसमें रिएक्टिव UI अपडेट होता है। Wrapper फ़िल्टर प्रेडिकेट और सॉर्ट डिस्क्रिप्टर के साथ NSFetchRequest स्वीकार करता है, और परिणाम — NSManagedObject की एक array — Core Data कॉन्टेक्स्ट में किसी भी बदलाव पर स्वचालित रूप से अपडेट हो जाती है। Apple Developer Documentation (2025) के अनुसार, @FetchRequest को SwiftUI वातावरण में managedObjectContext की आवश्यकता होती है और यह डायनामिक प्रेडिकेट का समर्थन करता है, जो Core Data और यूज़र इंटरफ़ेस के बीच रिएक्टिव कनेक्शन सुनिश्चित करता है।

मुख्य बिंदु

  • @FetchRequest — SwiftUI में रिएक्टिव Core Data फ़ेचिंग के लिए property wrapper
  • ऑटो-अपडेट UI जब Core Data में रिकॉर्ड जोड़े, हटाए या संशोधित किए जाएँ
  • प्रेडिकेट और सॉर्ट डिस्क्रिप्टर इनिशियलाइज़र में या property wrapper पैरामीटर के माध्यम से सेट किए जाते हैं
  • managedObjectContext View पदानुक्रम में @Environment के माध्यम से उपलब्ध होना चाहिए
  • डायनामिक प्रेडिकेट रनटाइम में फ़िल्टर शर्तों को बदलने की अनुमति देते हैं

SwiftUI में @FetchRequest क्या है?

@FetchRequest एक SwiftUI property wrapper है जो Core Data से FetchRequest बनाता और प्रबंधित करता है। इनिशियलाइज़ेशन पर, wrapper एक entity type, सॉर्टिंग के लिए NSSortDescriptor की array, और फ़िल्टरिंग के लिए एक वैकल्पिक NSPredicate स्वीकार करता है। परिणाम निर्दिष्ट NSManagedObject प्रकार की वस्तुओं की array के रूप में संग्रहीत होता है और persistence layer में परिवर्तन होने पर स्वचालित रूप से अपडेट हो जाता है।

@FetchRequest की मुख्य विशेषता रिएक्टिविटी है। जब Core Data में डेटा बदलता है (save, insert, delete, update), SwiftUI स्वचालित रूप से पुनः फ़ेच करता है और इस fetch request का उपयोग करने वाले सभी Views को पुनः रेंडर करता है। डेवलपर को मैन्युअल रूप से refresh कॉल करने, NSManagedObjectContextDidSaveNotification पर सब्सक्राइब करने या डेटा पुनः लोड करने की आवश्यकता नहीं है। SwiftUI पूरे सिंक्रोनाइज़ेशन चक्र का प्रबंधन करता है।

@FetchRequest के काम करने के लिए, SwiftUI वातावरण में @Environment(\.managedObjectContext) के माध्यम से एक NSManagedObjectContext उपलब्ध होना आवश्यक है। कॉन्टेक्स्ट आमतौर पर एप्लिकेशन रूट से पास किया जाता है, जहाँ NSPersistentContainer बनाया जाता है। मानक पैटर्न Core Data स्टैक को कॉन्फ़िगर करने और .environment() मॉडिफ़ायर के माध्यम से कॉन्टेक्स्ट पास करने के लिए ViewModel या App struct का उपयोग करना है।

FetchRequest की सॉर्टिंग और प्रेडिकेट

@FetchRequest फ़ेच को कॉन्फ़िगर करने के लिए कई पैरामीटर स्वीकार करता है। SortDescriptors — NSSortDescriptor की array जो रिकॉर्ड का क्रम निर्धारित करती है। Predicate — फ़िल्टरिंग के लिए NSPredicate, उदाहरण के लिए, केवल “पूर्ण” स्थिति वाले कार्यों को प्राप्त करना। Animation — डेटा बदलने पर सूची को अपडेट करने के लिए एनिमेशन।

Core Data प्रेडिकेट SQL-जैसे एक्सप्रेशन का प्रारूप उपयोग करते हैं: NSPredicate(format: “status == %@”, “completed”)। AND, OR और NOT के माध्यम से कई शर्तों को जोड़ा जा सकता है। SortDescriptors क्रम निर्धारित करते हैं: NSSortDescriptor(keyPath: \Task.dueDate, ascending: true)। कई फ़ील्ड द्वारा सॉर्ट करने के लिए, डिस्क्रिप्टर की array पास की जाती है — पहला प्राथमिक के रूप में लागू होता है, बाकी द्वितीयक के रूप में।

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 ?? "")
        }
    }
}

उदाहरण में, @FetchRequest सभी अधूरे कार्यों (isCompleted == NO) को प्राप्त करता है, पहले तिथि के अनुसार (आरोही), फिर प्राथमिकता के अनुसार (अवरोही) क्रमबद्ध। FetchedResults<Task> एक स्वचालित रूप से अपडेट होने वाला संग्रह है जो ForEach और List के लिए array की तरह व्यवहार करता है। .default एनिमेशन परिवर्तनों पर रिकॉर्ड की सुचारू उपस्थिति/गायब होना सुनिश्चित करता है।

List और डायनामिक डेटा के साथ @FetchRequest

@FetchRequest डायनामिक Core Data सूचियाँ प्रदर्शित करने के लिए List और ForEach के साथ पूरी तरह से मेल खाता है। फ़ेच परिणाम (FetchedResults) RandomAccessCollection प्रोटोकॉल के अनुरूप है, इसलिए इसे List और ForEach में सीधे उपयोग किया जा सकता है। रिकॉर्ड जोड़ने, हटाने या संशोधित करने पर, सूची स्वचालित रूप से एनिमेशन के साथ पुनः रेंडर होती है।

रिकॉर्ड हटाने के लिए, कॉन्टेक्स्ट विधि delete का उपयोग किया जाता है। रिकॉर्ड जोड़ने के लिए, एक नया NSManagedObject बनाया जाता है और save कॉल किया जाता है। सभी परिवर्तन viewContext के माध्यम से किए जाते हैं, जो @FetchRequest के साथ मिलकर डेटा स्थिरता सुनिश्चित करता है। संपादन के लिए, किसी विशिष्ट Core Data ऑब्जेक्ट के लिए @ObservedObject या @Bindable का उपयोग किया जाता है।

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: "plus") { 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()
    }
}

यह उदाहरण @FetchRequest के साथ पूर्ण CRUD प्रदर्शित करता है। जोड़ना: कॉन्टेक्स्ट के माध्यम से Task बनाना और save()। हटाना: कॉन्टेक्स्ट पर delete() और save()। अपडेट करना: प्रॉपर्टी टॉगल करना और save()। प्रत्येक save() के बाद, @FetchRequest स्वचालित रूप से डेटा पुनः प्राप्त करता है, और List एनिमेटेड रूप से अपडेट होती है। onDelete और onTapGesture मॉडिफ़ायर मानक iOS इंटरैक्शन प्रदान करते हैं।

@FetchRequest कोड उदाहरण

आइए रिकॉर्ड प्राप्त करने के लिए @FetchRequest के साथ एक पूर्ण जर्नल एप्लिकेशन उदाहरण देखें। खोज फ़ॉर्म एक डायनामिक प्रेडिकेट का उपयोग करता है: टेक्स्ट इनपुट करने पर, FetchRequest स्वचालित रूप से परिणाम अपडेट करता है, रिकॉर्ड को शीर्षक और सामग्री के अनुसार फ़िल्टर करता है। सॉर्टिंग निर्माण तिथि के अनुसार, नए से पुराने की ओर।

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)
    }
}

खोज के साथ जर्नल: searchable फ़ील्ड में टेक्स्ट इनपुट करने पर, title और content फ़ील्ड पर CONTAINS[c] (केस-असंवेदनशील खोज) के साथ एक NSPredicate बनाया जाता है। Init searchText स्वीकार करता है और संबंधित प्रेडिकेट के साथ FetchRequest बनाता है। Searchable मॉडिफ़ायर स्वचालित रूप से searchText अपडेट करता है, और @FetchRequest प्रेडिकेट परिवर्तन पर प्रतिक्रिया करता है और डेटा पुनः प्राप्त करता है।

एकाधिक फ़िल्टर वाले अधिक जटिल परिदृश्यों के लिए, AND/OR लॉजिक के साथ NSCompoundPredicate को संयोजित करें। @FetchRequest किसी भी जटिलता के प्रेडिकेट को समर्थन करता है, जिसमें relationship द्वारा फ़िल्टर करने के लिए नेस्टेड सबक्वेरी (SUBQUERY) शामिल है। हालाँकि, ध्यान रखें: जटिल प्रेडिकेट प्रदर्शन को प्रभावित करते हैं — बड़े डेटासेट (10,000 से अधिक रिकॉर्ड) के लिए, Core Data इंडेक्सिंग का उपयोग करें और fetchLimit के माध्यम से फ़ेच को सीमित करें।

रनटाइम में डायनामिक प्रेडिकेट

@FetchRequest predicate पैरामीटर के माध्यम से डायनामिक प्रेडिकेट का समर्थन करता है, जिसे रनटाइम में बदला जा सकता है। इसके लिए, एक वेरिएबल प्रेडिकेट के साथ @FetchRequest बनाया जाता है और Binding के माध्यम से पास किया जाता है। जब उपयोगकर्ता फ़िल्टर बदलता है — उदाहरण के लिए, कार्य श्रेणी चुनता है — प्रेडिकेट अपडेट होता है, और फ़ेच स्वचालित रूप से पुनः प्रारंभ होता है।

डायनामिक प्रेडिकेट @State या @Published प्रॉपर्टी के माध्यम से कार्यान्वित किए जाते हैं, जिसे @FetchRequest इनिशियलाइज़र में Binding के रूप में पास किया जाता है। SwiftUI इस Binding में परिवर्तन को ट्रैक करता है और नए प्रेडिकेट के साथ NSFetchRequest को पुनः बनाता है, स्वचालित रूप से सूची को अपडेट करता है।

अक्सर पूछे जाने वाले प्रश्न

@FetchRequest में managedObjectContext कैसे पास करें?

रूट View में @Environment(\.managedObjectContext) var viewContext जोड़ें और इसे .environment(\.managedObjectContext, context) मॉडिफ़ायर के माध्यम से पास करें। @FetchRequest का उपयोग करने वाले सभी चाइल्ड Views स्वचालित रूप से वातावरण से कॉन्टेक्स्ट प्राप्त करेंगे।

क्या @FetchRequest को View पुनः लोड किए बिना अपडेट किया जा सकता है?

हाँ, Core Data कॉन्टेक्स्ट को संशोधित करें: कोई ऑब्जेक्ट जोड़ें, हटाएँ या अपडेट करें और save() कॉल करें। @FetchRequest स्वचालित रूप से पुनः फ़ेच करेगा और UI अपडेट करेगा। save() के बिना जबरन अपडेट के लिए, viewContext.refreshAllObjects() का उपयोग करें।

@FetchRequest और @SectionedFetchRequest में क्या अंतर है?

@FetchRequest ऑब्जेक्ट की एक फ्लैट array लौटाता है। @SectionedFetchRequest परिणामों को निर्दिष्ट key path द्वारा sectionNameKeyPath के साथ UITableView के समान अनुभागों में समूहित करता है। सेक्शन हेडर वाली grouped सूचियों के लिए @SectionedFetchRequest का उपयोग करें।

Relationships के साथ @FetchRequest का उपयोग कैसे करें?

relationship द्वारा फ़िल्टर करने के लिए, डॉट नोटेशन का उपयोग करें: NSPredicate(format: “category.name == %@”, “Work”)। @FetchRequest स्वचालित रूप से SQLite में JOIN करता है। चयनित ऑब्जेक्ट के माध्यम से relationship तक पहुँचने के लिए, सामान्य NSManagedObject गुणों का उपयोग करें।

क्या @FetchRequest पेजिनेशन का समर्थन करता है?

@FetchRequest सीधे पेजिनेशन का समर्थन नहीं करता, क्योंकि यह रिएक्टिव अपडेट के साथ सभी रिकॉर्ड प्रदर्शित करने के लिए डिज़ाइन किया गया है। पेजिनेशन के लिए, fetchLimit/fetchOffset के साथ NSFetchRequest का उपयोग करें और सूची स्क्रॉल करने पर मैन्युअल रूप से डेटा लोड करें।

सारांश

  • @FetchRequest — SwiftUI में स्वचालित रिएक्टिव Core Data फ़ेचिंग के लिए property wrapper
  • सॉर्टिंग NSSortDescriptor की array द्वारा सेट की जाती है, फ़िल्टरिंग NSPredicate द्वारा
  • ऑटो-अपडेट UI Core Data कॉन्टेक्स्ट में किसी भी डेटा परिवर्तन पर
  • managedObjectContext View पदानुक्रम में @Environment के माध्यम से पास किया जाता है
  • डायनामिक प्रेडिकेट प्रेडिकेट पैरामीटर के साथ कस्टम init के माध्यम से कार्यान्वित किए जाते हैं
  • CRUD ऑपरेशन स्वचालित सूची सिंक्रोनाइज़ेशन के साथ viewContext के माध्यम से किए जाते हैं
  • उपयोग करें @FetchRequest Core Data प्रदर्शित करने के लिए, @SectionedFetchRequest grouped सूचियों के लिए

हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे

IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।

परियोजना पर चर्चा करें

यह भी पढ़ें