SwiftUI में @FetchRequest — Core Data से स्वचालित रूप से डेटा प्राप्त करने के लिए एक property wrapper जिसमें रिएक्टिव UI अपडेट होता है। Wrapper फ़िल्टर प्रेडिकेट और सॉर्ट डिस्क्रिप्टर के साथ NSFetchRequest स्वीकार करता है, और परिणाम — NSManagedObject की एक array — Core Data कॉन्टेक्स्ट में किसी भी बदलाव पर स्वचालित रूप से अपडेट हो जाती है। Apple Developer Documentation (2025) के अनुसार, @FetchRequest को SwiftUI वातावरण में managedObjectContext की आवश्यकता होती है और यह डायनामिक प्रेडिकेट का समर्थन करता है, जो Core Data और यूज़र इंटरफ़ेस के बीच रिएक्टिव कनेक्शन सुनिश्चित करता है।
मुख्य बिंदु
@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 फ़ेच को कॉन्फ़िगर करने के लिए कई पैरामीटर स्वीकार करता है। SortDescriptors — NSSortDescriptor की array जो रिकॉर्ड का क्रम निर्धारित करती है। Predicate — फ़िल्टरिंग के लिए NSPredicate, उदाहरण के लिए, केवल “पूर्ण” स्थिति वाले कार्यों को प्राप्त करना। Animation — डेटा बदलने पर सूची को अपडेट करने के लिए एनिमेशन।
Core Data प्रेडिकेट SQL-जैसे एक्सप्रेशन का प्रारूप उपयोग करते हैं: NSPredicate(format: “status == %@”, “completed”)। AND, OR और NOT के माध्यम से कई शर्तों को जोड़ा जा सकता है। SortDescriptors क्रम निर्धारित करते हैं: NSSortDescriptor(keyPath: \Task.dueDate, ascending: true)। कई फ़ील्ड द्वारा सॉर्ट करने के लिए, डिस्क्रिप्टर की array पास की जाती है — पहला प्राथमिक के रूप में लागू होता है, बाकी द्वितीयक के रूप में।
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 एनिमेशन परिवर्तनों पर रिकॉर्ड की सुचारू उपस्थिति/गायब होना सुनिश्चित करता है।
@FetchRequest डायनामिक Core Data सूचियाँ प्रदर्शित करने के लिए List और ForEach के साथ पूरी तरह से मेल खाता है। फ़ेच परिणाम (FetchedResults) RandomAccessCollection प्रोटोकॉल के अनुरूप है, इसलिए इसे List और ForEach में सीधे उपयोग किया जा सकता है। रिकॉर्ड जोड़ने, हटाने या संशोधित करने पर, सूची स्वचालित रूप से एनिमेशन के साथ पुनः रेंडर होती है।
रिकॉर्ड हटाने के लिए, कॉन्टेक्स्ट विधि delete का उपयोग किया जाता है। रिकॉर्ड जोड़ने के लिए, एक नया NSManagedObject बनाया जाता है और save कॉल किया जाता है। सभी परिवर्तन viewContext के माध्यम से किए जाते हैं, जो @FetchRequest के साथ मिलकर डेटा स्थिरता सुनिश्चित करता है। संपादन के लिए, किसी विशिष्ट Core Data ऑब्जेक्ट के लिए @ObservedObject या @Bindable का उपयोग किया जाता है।
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 स्वचालित रूप से परिणाम अपडेट करता है, रिकॉर्ड को शीर्षक और सामग्री के अनुसार फ़िल्टर करता है। सॉर्टिंग निर्माण तिथि के अनुसार, नए से पुराने की ओर।
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 को पुनः बनाता है, स्वचालित रूप से सूची को अपडेट करता है।
अक्सर पूछे जाने वाले प्रश्न
रूट View में @Environment(\.managedObjectContext) var viewContext जोड़ें और इसे .environment(\.managedObjectContext, context) मॉडिफ़ायर के माध्यम से पास करें। @FetchRequest का उपयोग करने वाले सभी चाइल्ड Views स्वचालित रूप से वातावरण से कॉन्टेक्स्ट प्राप्त करेंगे।
हाँ, Core Data कॉन्टेक्स्ट को संशोधित करें: कोई ऑब्जेक्ट जोड़ें, हटाएँ या अपडेट करें और save() कॉल करें। @FetchRequest स्वचालित रूप से पुनः फ़ेच करेगा और UI अपडेट करेगा। save() के बिना जबरन अपडेट के लिए, viewContext.refreshAllObjects() का उपयोग करें।
@FetchRequest ऑब्जेक्ट की एक फ्लैट array लौटाता है। @SectionedFetchRequest परिणामों को निर्दिष्ट key path द्वारा sectionNameKeyPath के साथ UITableView के समान अनुभागों में समूहित करता है। सेक्शन हेडर वाली grouped सूचियों के लिए @SectionedFetchRequest का उपयोग करें।
relationship द्वारा फ़िल्टर करने के लिए, डॉट नोटेशन का उपयोग करें: NSPredicate(format: “category.name == %@”, “Work”)। @FetchRequest स्वचालित रूप से SQLite में JOIN करता है। चयनित ऑब्जेक्ट के माध्यम से relationship तक पहुँचने के लिए, सामान्य NSManagedObject गुणों का उपयोग करें।
@FetchRequest सीधे पेजिनेशन का समर्थन नहीं करता, क्योंकि यह रिएक्टिव अपडेट के साथ सभी रिकॉर्ड प्रदर्शित करने के लिए डिज़ाइन किया गया है। पेजिनेशन के लिए, fetchLimit/fetchOffset के साथ NSFetchRequest का उपयोग करें और सूची स्क्रॉल करने पर मैन्युअल रूप से डेटा लोड करें।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें