SwiftUI میں @FetchRequest — Core Data سے خود بخود ڈیٹا حاصل کرنے کے لیے ایک property wrapper جس میں رد عمل والی انٹرفیس اپ ڈیٹ ہوتی ہے۔ Wrapper فلٹر پیش گوئوں اور ترتیب کے ساتھ NSFetchRequest قبول کرتا ہے، اور نتیجہ — NSManagedObject کی ایک صف — Core Data کے سیاق میں کسی بھی تبدیلی پر خود بخود اپ ڈیٹ ہو جاتا ہے۔ Apple Developer Documentation (2025) کے مطابق، @FetchRequest کو SwiftUI ماحول میں managedObjectContext کی ضرورت ہے اور یہ متحرک پیش گوئوں کو سپورٹ کرتا ہے، جو Core Data اور صارف انٹرفیس کے درمیان رد عمل کا تعلق فراہم کرتا ہے۔
اہم نکات
@FetchRequest ایک SwiftUI property wrapper ہے جو Core Data سے FetchRequest بناتا اور اس کا انتظام کرتا ہے۔ ابتدا کے وقت، wrapper ایک entity type، ترتیب کے لیے NSSortDescriptor کی صف، اور فلٹرنگ کے لیے ایک اختیاری NSPredicate قبول کرتا ہے۔ نتیجہ مخصوص NSManagedObject قسم کی اشیاء کی صف کے طور پر محفوظ ہوتا ہے اور استحکام کی تہہ میں تبدیلی ہونے پر خود بخود اپ ڈیٹ ہو جاتا ہے۔
@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 کی صف جو ریکارڈ کی ترتیب کا تعین کرتی ہے۔ Predicate — فلٹرنگ کے لیے NSPredicate، مثال کے طور پر، صرف «مکمل» حیثیت والے کاموں کو حاصل کرنا۔ Animation — ڈیٹا تبدیل ہونے پر فہرست کو اپ ڈیٹ کرنے کے لیے حرکت۔
Core Data کی پیش گوئیاں SQL جیسے اظہار کی شکل استعمال کرتی ہیں: NSPredicate(format: «status == %@», «completed»)۔ AND، OR اور NOT کے ذریعے متعدد شرائط کو جوڑا جا سکتا ہے۔ SortDescriptors ترتیب کی وضاحت کرتے ہیں: NSSortDescriptor(keyPath: \Task.dueDate, ascending: true)۔ متعدد فیلڈز کے لحاظ سے ترتیب دینے کے لیے، وصف کنندگان کی ایک صف منتقل کی جاتی ہے — پہلا بنیادی کے طور پر لاگو ہوتا ہے، باقی ثانوی کے طور پر۔
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 کے لیے صف کی طرح برتاؤ کرتا ہے۔ .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 کسی بھی پیچیدگی کی پیش گوئیوں کو سپورٹ کرتا ہے، بشمول تعلق کے لحاظ سے فلٹر کرنے کے لیے نیسٹڈ ذیلی سوالات (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 خود بخود دوبارہ بازیافت کرے گا اور انٹرفیس کو اپ ڈیٹ کرے گا۔ save() کے بغیر مجبوری اپ ڈیٹ کے لیے، viewContext.refreshAllObjects() استعمال کریں۔
@FetchRequest اشیاء کی ایک فلیٹ صف لوٹاتا ہے۔ @SectionedFetchRequest نتائج کو مخصوص کلیدی راستے کے مطابق sectionNameKeyPath کے ساتھ UITableView کی طرح حصوں میں گروپ کرتا ہے۔ حصوں کے عنوان والی گروپ شدہ فہرستوں کے لیے @SectionedFetchRequest استعمال کریں۔
تعلق کے لحاظ سے فلٹر کرنے کے لیے، ڈاٹ نوٹیشن استعمال کریں: NSPredicate(format: «category.name == %@», «Work»)۔ @FetchRequest خود بخود SQLite میں JOIN کرتا ہے۔ منتخب آبجیکٹ کے ذریعے تعلق تک رسائی کے لیے، عام NSManagedObject خصوصیات استعمال کریں۔
@FetchRequest براہ راست صفحہ بندی کو سپورٹ نہیں کرتا، کیونکہ یہ رد عمل والی اپ ڈیٹ کے ساتھ تمام ریکارڈ ظاہر کرنے کے لیے ڈیزائن کیا گیا ہے۔ صفحہ بندی کے لیے، fetchLimit/fetchOffset کے ساتھ NSFetchRequest استعمال کریں اور فہرست اسکرول ہونے پر دستی طور پر ڈیٹا لوڈ کریں۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں