Combine — Apple کا ری ایکٹیو پروگرامنگ فریم ورک ہے، جو iOS 13 میں متعارف کرایا گیا۔ Apple Documentation, 2025 کے مطابق، Combine غیر متزامن واقعات کی پروسیسنگ کے لیے ایک مشترکہ اعلانیہ API فراہم کرتا ہے۔ Publisher ڈیٹا کا ذریعہ متعین کرتا ہے، جبکہ Subscriber اسے وصول کرنے کے لیے سبسکرائب ہوتا ہے۔
اہم نکات
Combine — وقت کے ساتھ غیر متزامن واقعات کی پروسیسنگ کے لیے ایک اعلانیہ Swift فریم ورک ہے۔ callback طریقوں کے برعکس، Combine آپریٹرز کی زنجیر کے ذریعے ڈیٹا پروسیسنگ پائپ لائنز کی وضاحت کرنے کی اجازت دیتا ہے۔ یہ فریم ورک Foundation (URLSession, Timer, NotificationCenter) اور SwiftUI (ObservableObject, @Published) کے ساتھ مربوط ہے۔
کوئی بھی قسم جو Publisher پروٹوکول کو لاگو کرتی ہے، اسے Output (قدروں کی قسم) اور Failure (خرابی کی قسم) متعین کرنا ضروری ہے۔ Publisher سبسکرپشن تک فعال نہیں ہوتا — یہ صرف subscribe کال کرنے کے بعد واقعات بھیجنا شروع کرتا ہے۔ یہ سرد سیمنٹک ہے، جو ری ایکٹیو اسٹریمز کی خصوصیت ہے اور کارکردگی کو بڑھاتا ہے۔
Subscriber تین طریقوں کے ذریعے واقعات وصول کرتا ہے: receive(subscription:) — demand کے ساتھ سبسکرپشن کی تصدیق؛ receive(_:) — نئی قدر وصول کرنا؛ receive(completion:) — کامیابی یا خرابی کے ساتھ اسٹریم کی تکمیل۔ Demand قدروں کی تعداد متعین کرتا ہے جو Subscriber وصول کرنے کے لیے تیار ہے — یہ backpressure کا طریقہ کار ہے۔
Apple بہت سے بلٹ ان Publisher فراہم کرتا ہے: Just ایک قدر بھیجتا ہے اور ختم ہو جاتا ہے، Future — بندش کے ساتھ غیر متزامن نتیجہ، Deferred — سبسکرپشن کے لمحے تک Publisher کی تخلیق کو ملتوی کرتا ہے۔ URLSession.dataTaskPublisher نیٹ ورک کی درخواست کو ری ایکٹیو اسٹریم میں تبدیل کرتا ہے۔ Timer.publish متواتر ٹائمر بناتا ہے۔ NotificationCenter.default.publisher اطلاعوں کو Publisher میں تبدیل کرتا ہے۔ یہ انضمام دستی پل کے بغیر واقعات کی سبسکرپشن کی اجازت دیتے ہیں۔
کمبائن میں Publisher اور Subscriber Subscription پروٹوکول کے ذریعے جڑے ہوئے ہیں۔ Subscription ایک مربوط آبجیکٹ ہے جو ڈیٹا کے بہاؤ کو کنٹرول کرتا ہے۔ ڈیولپر کو اپنی Publisher اقسام بنانے کی ضرورت نہیں — Apple بلٹ ان فراہم کرتا ہے: Just, Future, Deferred, Fail, Empty، اور URLSession اور Timer کے لیے Publisher۔
Subject — ایک Publisher ہے جس میں دستی طور پر قدریں بھیجی جا سکتی ہیں۔ PassthroughSubject حالت محفوظ نہیں کرتا: سبسکرائبر صرف وہ واقعات وصول کرتا ہے جو سبسکرپشن کے بعد رونما ہوئے۔ CurrentValueSubject، RxSwift میں BehaviorRelay کے مشابہ، موجودہ قدر محفوظ کرتا ہے اور فوری طور پر نئے سبسکرائبر کو منتقل کرتا ہے۔
کمبائن میں backpressure کا طریقہ کار ڈیٹا کی منتقلی کی رفتار کو منظم کرتا ہے۔ Subscriber subscription.request(.unlimited) یا subscription.request(.max(N)) کے ذریعے Publisher کو بتاتا ہے کہ وہ کتنی قدریں پروسیس کرنے کے لیے تیار ہے۔ یہ producer اور consumer کی غیر یکساں رفتار پر بفر کے بہاؤ کو روکتا ہے۔
کمبائن میں 100 سے زیادہ آپریٹرز شامل ہیں، جو زمروں میں تقسیم ہیں: تبدیلی (map, tryMap, flatMap)، فلٹریشن (filter, compactMap, removeDuplicates)، امتزاج (combineLatest, merge, zip)، وقت کا انتظام (debounce, throttle, delay) اور خرابی کا انتظام (catch, replaceError, retry)۔
combineLatest آپریٹر دو Publisher کی تازہ ترین قدروں کو یکجا کرتا ہے — جب بھی ان میں سے کوئی بھی نئی قدر بھیجتا ہے، بندش دونوں تازہ ترین قدروں کے ساتھ کال کی جاتی ہے۔ یہ آپریٹر فارم کی توثیق کے لیے ناگزیر ہے، جہاں ایک ساتھ متعدد ان پٹ فیلڈز کی حالت کو ٹریک کرنا ضروری ہے۔
debounce آپریٹر قدروں کی اشاعت میں اس وقت تک تاخیر کرتا ہے جب تک کہ نئے واقعات کے بغیر متعین وقفہ گزر نہ جائے۔ یہ سرچ بارز کے لیے انتہائی اہم ہے: صارف کے 300-500 ms تک ٹائپ کرنا بند کرنے کے بعد ہی سرور پر درخواست بھیجی جاتی ہے، جس سے لوڈ 5-10 گنا کم ہو جاتا ہے۔
کمبائن آپریٹرز کی سطح پر خرابی کے انتظام کی کئی حکمت عملیاں پیش کرتا ہے۔ catch Failure کو پکڑتا ہے اور Publisher کو فال بیک سے بدل دیتا ہے — اسٹریم بغیر کریش کے جاری رہتا ہے۔ replaceError(with:) خرابی کی جگہ ڈیفالٹ قدر ڈال دیتا ہے۔ retry(_:) ناکامی پر متعین تعداد میں سبسکرپشن دہراتا ہے۔ اہم: Publisher کی دستخط میں Never قسم کی خرابی ضمانت دیتی ہے کہ اسٹریم کبھی خرابی پر ختم نہیں ہوگا — یہ SwiftUI میں Publisher کو Failure کی پروسیسنگ کے بغیر استعمال کرنے کی اجازت دیتا ہے۔
پہلی مثال Just کے ساتھ بنیادی کام دکھاتی ہے — Publisher جو ایک قدر بھیجتا ہے اور ختم ہو جاتا ہے:
let publisher = Just("Hello Combine")
publisher
.sink(receiveCompletion: { completion in
print("مکمل: \(completion)")
}, receiveValue: { value in
print("موصول: \(value)")
})
دوسری مثال کمبائن کے URLSession کے ساتھ انضمام کو نیٹ ورک کی درخواست اور مرکزی تھریڈ پر نتیجہ کی پروسیسنگ کے ساتھ دکھاتی ہے:
let url = URL(string: "https://api.example.com")!
URLSession.shared
.dataTaskPublisher(for: url)
.map { $0.data }
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { completion in
if case .failure(let error) = completion {
print("خرابی: \(error)")
}
}, receiveValue: { data in
print("موصول کردہ ڈیٹا: \(data.count)")
})
تیسری مثال — حالت کے انتظام کے لیے CurrentValueSubject کا استعمال:
let counter = CurrentValueSubject<Int, Never>(0)
counter
.sink { value in
print("شمار کنندہ: \(value)")
}
counter.send(1) // آؤٹ پٹ: شمار کنندہ: 1
counter.send(2) // آؤٹ پٹ: شمار کنندہ: 2
print(counter.value) // آؤٹ پٹ: 2
Combine اور RxSwift ایک ہی کام حل کرتے ہیں — ری ایکٹیو پروگرامنگ، لیکن مختلف طریقوں سے۔ Combine — Apple کا مقامی فریم ورک ہے، جو سسٹم میں شامل ہے: انحصار کی تنصیب کی ضرورت نہیں، SwiftUI اور Foundation کے ساتھ مربوط ہے۔ RxSwift — iOS 9+ کی معاونت اور آپریٹرز کے وسیع تر سیٹ کے ساتھ ایک تھرڈ پارٹی لائبریری ہے۔
عام منظرناموں میں Combine کی کارکردگی C میں مقامی نفاذ کی وجہ سے زیادہ ہے۔ RxSwift ڈیبگنگ کے لیے زیادہ ٹولز فراہم کرتا ہے (RxSwift.Resources.total, Debug)، لیکن اس کا آبجیکٹ اورینٹڈ آرکیٹیکچر بڑے ڈیٹا اسٹریمز پر کم موثر ہو سکتا ہے۔ ان کے درمیان انتخاب — صلاحیتوں اور انضمام کے درمیان ایک سمجھوتہ ہے۔
ایک اہم فرق — backpressure کا ماڈل۔ کمبائن میں Subscriber Subscription کے ذریعے demand کا انتظام کرتا ہے، جو اسٹریم کی رفتار پر واضح کنٹرول دیتا ہے۔ RxSwift میں backpressure ڈیفالٹ طور پر کنٹرول نہیں ہوتی — Observable تمام قدریں بھیجتا ہے، اور Subscriber انہیں وصول ہونے پر پروسیس کرتا ہے۔ بڑے ڈیٹا اسٹریمز کے لیے Combine زیادہ پیش قیاسی اور میموری کے لحاظ سے محفوظ ہے۔
Combine زبان کی سطح پر SwiftUI کے ساتھ گہرا مربوط ہے۔ @Published Publisher بناتا ہے، ObservableObject objectWillChange Publisher فراہم کرتا ہے۔ SwiftUI View خود بخود ان Publisher پر سبسکرائب ہوتی ہے اور تبدیلیوں پر دوبارہ پینٹ ہوتی ہے۔ UIKit کے لیے CombineCocoa جیسی تھرڈ پارٹی ریپنگز ہیں، لیکن Combine ابتدائی طور پر SwiftUI کے لیے ڈیزائن کیا گیا تھا، اس لیے UIKit میں اس کا انضمام اضافی کوڈ کی ضرورت ہے۔ RxSwift، اس کے برعکس، UIKit کے لیے بھرپور ایکو سسٹم رکھتا ہے: RxCocoa تمام UI عناصر کے لیے ری ایکٹیو ریپنگز فراہم کرتا ہے۔
Combine Core Data کے ساتھ NSFetchedResultsController Publisher کے ذریعے انضمام کو سپورٹ کرتا ہے۔ Publisher Core Data اسٹیک کی ہر تبدیلی پر نیا ڈیٹا بھیجتا ہے: ریکارڈز کا اضافہ، حذف، اپ ڈیٹ۔ یہ دستی reloadData کال کے بغیر ری ایکٹیو لسٹیں بنانے کی اجازت دیتا ہے۔ UIApplication.willResignActiveNotification کے لیے Combine کو NotificationCenter Publisher کے ساتھ ملا کر، ڈیولپر بغیر ڈیلیگیٹس اور کال بیکس کے ایپلیکیشن کے پورے لائف سائیکل کے لیے ری ایکٹیو پرت بناتا ہے۔ ObservableObject کلاسز کے لیے SwiftUI خود بخود View کو @Published پراپرٹیز کی تبدیلی پر اپ ڈیٹ کرتا ہے — Combine بغیر دستی کوڈ کی ایک لائن کے پوری کڑی فراہم کرتا ہے۔ Combine کوڈ کی ماڈیولر ٹیسٹنگ XCTestExpectation اور Publisher.sink کے ذریعے ٹیسٹ کیسز میں Scheduler کو ImmediateScheduler کے ذریعے الگ کر کے کی جاتی ہے۔
UIKit پروجیکٹس میں Combine کے ساتھ کام کرتے وقت، ڈیولپرز اکثر sink کے ذریعے سبسکرپشن استعمال کرتے ہیں اور AnyCancellable کو Set میں محفوظ کرتے ہیں۔ عام پیٹرن: ViewController ویو بناتا ہے، cancellables محفوظ کرتا ہے، ViewModel سے Publisher پر سبسکرائب ہوتا ہے۔ deinit پر تمام سبسکرپشنز Cancellables کلیکشن کے ذریعے خود بخود منسوخ ہو جاتی ہیں۔ UIControl کے ساتھ Combine میں صحیح کام کرنے کے لیے publisher(for:) ایکسٹینشن کے ذریعے UIControl.Event Publisher استعمال کیا جا سکتا ہے۔
Combine کی ڈیبگنگ print() یا handleEvents() آپریٹر کے ذریعے کی جاتی ہے۔ print(String) تمام واقعات کو لاگ کرتا ہے: receive subscription, request demand, receive value, receive completion۔ handleEvents زیادہ باریک کنٹرول دیتا ہے: Publisher کے لائف سائیکل کے ہر مرحلے کے لیے بندشیں متعین کی جا سکتی ہیں۔ جانچ کے لیے CombineExpectations موجود ہے — ایک لائبریری جو ورچوئل ٹائم اور demand کنٹرول کے ساتھ ٹیسٹوں میں یہ جانچنے کی اجازت دیتی ہے کہ Publisher متوقع قدریں بھیجتا ہے۔
Combine SwiftUI میں فارمز کے انتظام کے لیے فعال طور پر استعمال ہوتا ہے: ہر @Published پراپرٹی Publisher بناتی ہے، SwiftUI اسے View.body کے ذریعے سبسکرائب کرتا ہے۔ متعدد Publisher کو combineLatest کے ذریعے ملا کر، فارم کی توثیق اعلانیہ ہو جاتی ہے: ہر Publisher ایک فیلڈ کو ٹریک کرتا ہے، combineLatest تمام قدروں کو جمع کرتا ہے، map انہیں جانچتا ہے اور Submit بٹن کی حالت لوٹاتا ہے۔ Publishers.Merge ایک ہی قسم کے متعدد Publisher کو ایک میں ملا دیتا ہے — مختلف کنٹرولز سے واقعات کو ایک اسٹریم میں جمع کرنے کے لیے مفید۔
UIKit کے ساتھ Combine کے انضمام کے لیے UIControl Publisher ایکسٹینشن کے ذریعے استعمال کریں: button.publisher(for: .touchUpInside) Publisher لوٹاتا ہے جو دبانے پر واقعہ بھیجتا ہے۔ CombineCocoa — کمیونٹی کی ایک لائبریری ہے جو تمام UIControl واقعات، UITextView.text، UIScrollView.contentOffset کے لیے Publisher فراہم کرتی ہے۔ منسوخی پر cancellables Store deinit میں صاف ہو جاتا ہے، اس بات کی ضمانت دیتے ہوئے کہ کوئی بھی سبسکرپشن اپنے مالک سے زیادہ زندہ نہیں رہے گی۔ متعدد حالتوں والے UIControl کے لیے Publishers.MergeMany کا استعمال Publisher کو ایک صف میں جمع کرنے کے لیے کریں۔
اکثر پوچھے گئے سوالات
Combine iOS 13, macOS 10.15, tvOS 13 اور watchOS 6 سے دستیاب ہے۔ یہ پرانے ورژنز کی معاونت کی ضرورت والے پروجیکٹس میں اس کے استعمال کو محدود کرتا ہے۔ iOS 12 اور اس سے نیچے کے لیے RxSwift یا تھرڈ پارٹی لائبریریز استعمال کی جاتی ہیں۔
PassthroughSubject حالت محفوظ نہیں کرتا اور نئے سبسکرائبرز کو آخری قدر نہیں دہراتا — وہ صرف مستقبل کے واقعات وصول کرتے ہیں۔ CurrentValueSubject موجودہ قدر محفوظ کرتا ہے اور فوری طور پر اسے نئے سبسکرائبر کو منتقل کرتا ہے۔ CurrentValueSubject.value موجودہ قدر کو ہم وقت طور پر پڑھنے اور لکھنے کی اجازت دیتا ہے۔
Combine SwiftUI کی بنیاد ہے: @Published Publisher بناتا ہے، ObservableObject objectWillChange Publisher استعمال کرتا ہے۔ SwiftUI View خود بخود Combine پائپ لائن کے ذریعے @ObservedObject اور @StateObject پر سبسکرائب ہوتی ہے، پراپرٹی کی تبدیلی پر View کو دوبارہ پینٹ کرتی ہے۔
Backpressure — ڈیٹا کی منتقلی کی رفتار کو منظم کرنے کا طریقہ کار ہے۔ Subscriber Subscription کو بتاتا ہے کہ وہ کتنی قدریں پروسیس کرنے کے لیے تیار ہے (demand)۔ Publisher درخواست سے زیادہ قدریں نہیں بھیج سکتا۔ یہ نیٹ ورک ساکٹ سے بڑے ڈیٹا اسٹریمز کے ساتھ کام کرتے وقت اہم ہے۔
catch آپریٹر خرابی کو پکڑتا ہے اور Publisher کو فال بیک سے بدل دیتا ہے۔ replaceError خرابی کو ڈیفالٹ قدر سے بدل دیتا ہے۔ retry خرابی پر متعین تعداد میں سبسکرپشن دہراتا ہے۔ تمام آپریٹرز کو subscribe سے پہلے رکھنا چاہیے تاکہ Failure پر کریش سے بچا جا سکے۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں