Weak Reference (کمزور حوالہ) ایک آبجیکٹ کا حوالہ ہے جو ARC میں اس کے برقرار رکھنے کے شمار کو نہیں بڑھاتا۔ Apple Swift Language Guide, 2026 کے مطابق، کمزور حوالوں کا اعلان weak کلیدی لفظ سے کیا جاتا ہے اور یہ ہمیشہ اختیاری ہوتے ہیں۔ جب آبجیکٹ آزاد ہوتا ہے، تو اس کے تمام کمزور حوالے خود بخود nil پر سیٹ ہو جاتے ہیں، جو لٹکتے پوائنٹرز کو روکتا ہے اور کمزور حوالوں کو برقرار رکھنے کے چکر توڑنے کے لیے ایک محفوظ طریقہ کار بناتا ہے۔
اہم نکات
weak کلیدی لفظ؛ قسم ہمیشہ اختیاری (?)Weak Reference ARC (Automatic Reference Counting) میں کسی آبجیکٹ کا غیر مالکانہ حوالہ ہے۔ مضبوط حوالے کے برعکس، جو آبجیکٹ کے retain count کو بڑھاتا ہے اور اس کی زندگی کی ضمانت دیتا ہے، کمزور حوالہ آبجیکٹ کو آزاد ہونے دیتا ہے چاہے اس کا اب بھی حوالہ دیا جا رہا ہو۔ خاتمے کے بعد، کمزور حوالہ خود بخود nil پر سیٹ ہو جاتا ہے — اسے zeroing weak کہا جاتا ہے۔
Zeroing weak Swift اور Objective-C رن ٹائم کی ایک اہم خصوصیت ہے۔ جب کسی آبجیکٹ کا حوالہ شمار صفر تک پہنچتا ہے اور آبجیکٹ ختم ہو جاتا ہے، رن ٹائم اس آبجیکٹ کے تمام کمزور حوالوں (ایک خصوصی کمزور جدول میں ذخیرہ شدہ) کو گزرتا ہے اور انہیں nil پر سیٹ کرتا ہے۔ یہ یقینی بناتا ہے کہ کمزور حوالوں کے ذریعے آزاد میموری تک رسائی (use-after-free) ناممکن ہے — کوئی بھی پڑھائی nil لوٹاتی ہے۔
Apple WWDC 2012 Session 406 کے مطابق، zeroing weak حوالوں نے لٹکتے پوائنٹرز سے متعلق کریش بگز کی ایک پوری کلاس کو ختم کر دیا، جو دستی میموری مینجمنٹ (MRR) میں عام تھے۔ MRR میں، کمزور حوالے صرف __unsafe_unretained کے طور پر موجود تھے — وہ صفر نہیں ہوتے تھے، اور ختم شدہ آبجیکٹ تک رسائی EXC_BAD_ACCESS کا سبب بنتی تھی۔
آئیے Apple ماحولیاتی نظام کی دونوں زبانوں میں کمزور حوالوں کے اعلان کا نحو دیکھتے ہیں۔ مشترکہ رن ٹائم کے باوجود، نحو مختلف ہے، لیکن معنی یکساں ہیں۔
Swift میں، کمزور حوالوں کا اعلان var سے پہلے weak کلیدی لفظ سے کیا جاتا ہے۔ قسم ہمیشہ اختیاری (قسم?) ہونی چاہیے، کیونکہ حوالہ کسی بھی وقت nil ہو سکتا ہے۔ مستقل (let) weak نہیں ہو سکتے — صرف متغیر۔
class ViewController: UIViewController {
// weak properties: only var, only optional
weak var delegate: ViewControllerDelegate?
weak var parentView: UIView?
weak var completionHandler: ((Bool) -> Void)? // ⚠️ بندشاں weak ذخیرہ نہیں کرتیں
// ⬆️ غلطی: weak صرف class اقسام پر لاگو کیا جا سکتا ہے، closures پر نہیں
}
اہم: weak صرف class مثالوں (class اقسام)، AnyObject، اور AnyObject سے ماخوذ پروٹوکولز پر لاگو ہوتا ہے۔ Struct، enum اور بندشاں weak نہیں ہو سکتیں — یہ قدر کی اقسام ہیں اور ARC میں حصہ نہیں لیتے۔
Objective-C میں، کمزور خصوصیات کا اعلان __weak خاصیت یا خاصیت کے اعلان میں weak modifier کے ذریعے کیا جاتا ہے:
// Objective-C: weak property
@interface MyViewController : UIViewController
@property (weak, nonatomic) id<MyDelegate> delegate;
@end
// مقامی weak متغیر
__weak MyObject *weakRef = someStrongObject;
Objective-C رن ٹائم بھی zeroing weak فراہم کرتا ہے، لیکن اضافی طور پر C ڈھانچوں اور کچھ Core Foundation آبجیکٹس کے ساتھ weak کے استعمال کو روکتا ہے۔ ان کے لیے، __unsafe_unretained استعمال کیا جاتا ہے — zeroing کے بغیر۔
کمزور حوالے عالمگیر حل نہیں ہیں، بلکہ مخصوص منظرناموں کے لیے ایک آلہ ہیں۔ ہر جگہ weak استعمال کرنا غیر ضروری پیچیدگی کا باعث بنتا ہے اور پڑھنے کی اہلیت کو خراب کرتا ہے۔ آئیے صحیح استعمال کے منظرناموں کو دیکھتے ہیں۔
مندوبین — weak کے لیے بنیادی منظرنامہ۔ مالک آبجیکٹ (مثلاً UITableView) خود پر ایک مضبوط حوالہ رکھتا ہے، جبکہ مندوب (UIViewController) کو جدول کا مالک نہیں ہونا چاہیے۔ Apple SDK ضمانت دیتا ہے کہ تمام مندوبین اور dataSource weak ہیں۔ اپنے پروٹوکولز کے لیے، ہمیشہ weak var delegate استعمال کریں۔
جب کسی بچے آبجیکٹ کو اپنے والدین کا حوالہ دینے کی ضرورت ہوتی ہے (مثلاً ChildViewController کوآرڈینیٹر تک رسائی)، کمزور حوالہ استعمال کریں۔ والدین بچے کا مالک ہے (strong)، بچہ والدین کا مشاہدہ کرتا ہے (weak) — برقرار رکھنے کا چکر ختم ہو جاتا ہے۔
Capture list [weak self] — کلاس کی خصوصیات کے طور پر ذخیرہ شدہ بندشوں میں برقرار رکھنے کے چکروں سے بچنے کا معیاری طریقہ۔ اگر self بندش مکمل ہونے سے پہلے ختم ہو سکتا ہے، تو weak self لازمی ہے۔
| منظرنامہ | Weak | Strong |
|---|---|---|
| مندوب | ✅ ہمیشہ weak | ❌ برقرار رکھنے کا چکر |
| والدین → بچہ | ❌ ضروری نہیں (والدین کو مالک ہونا چاہیے) | ✅ Strong |
| بچہ → والدین | ✅ Weak | ❌ برقرار رکھنے کا چکر |
| غیر متوازی کال بیک | ✅ [weak self] | ❌ برقرار رکھنے کے چکر کا خطرہ |
| مضبوط جوڑ (owned) | ❌ unowned | ✅ Strong |
عمومی اصول: اگر آبجیکٹ A، B کا مالک ہے (A → B strong)، تو B → A weak یا unowned ہونا چاہیے۔ مضبوط حوالوں کی سمت ہمیشہ مالک سے ماتحت کی طرف ہونی چاہیے۔
weak اور unowned دونوں retain count نہیں بڑھاتے، لیکن آبجیکٹ کے خاتمے کے بعد رویے میں مختلف ہیں۔ ان کے درمیان انتخاب زندگی کی ضمانتوں کا معاملہ ہے۔
Weak: خود بخود nil ہو جاتا ہے، قسم ہمیشہ اختیاری، استعمال سے پہلے کھولنے کی ضرورت۔ محفوظ — nil تک رسائی کریش کا سبب نہیں بنتی۔
Unowned: nil نہیں ہوتا، قسم غیر اختیاری۔ اگر آبجیکٹ ختم ہو جائے تو unowned حوالہ لٹکتا پوائنٹر بن جاتا ہے — اس تک رسائی رن ٹائم کریش کا سبب بنتی ہے۔ Unowned فرض کرتا ہے کہ آبجیکٹ حوالہ دینے والی طرف سے کم از کم اتنی ہی دیر زندہ رہتا ہے۔
Weak منتخب کریں اگر: آبجیکٹ کسی بھی وقت ختم ہو سکتا ہے (اسکرین بند ہونے کے بعد مندوب)، آپ آبجیکٹ کی زندگی کو کنٹرول نہیں کرتے، یا ضمانتوں کے بارے میں یقین نہیں ہے۔ Weak عالمگیر محفوظ انتخاب ہے۔
Unowned منتخب کریں اگر: آبجیکٹ کی ضمانت ہے کہ حوالہ دینے والے آبجیکٹ سے پہلے ختم نہیں ہوگا (مثلاً Customer → CreditCard، جہاں کارڈ گاہک کے بغیر موجود نہیں ہے)۔ Unowned بغیر کھولے ایک غیر اختیاری API فراہم کرتا ہے، جو کوڈ میں زیادہ آسان ہے۔
class Order {
let id: Int
var items: [Item] = []
init(id: Int) { self.id = id }
// مضبوط تعلق: Order کا Item پر مالکیت
func addItem(name: String) {
let item = Item(name: name, order: self)
items.append(item)
}
}
class Item {
let name: String
unowned let order: Order // ✅ unowned — Item Order کے بغیر نہیں رہتا
init(name: String, order: Order) {
self.name = name
self.order = order
}
}
// weak کے ساتھ مثال: زندگی کی ضمانت کے بغیر مندوب
protocol NetworkServiceDelegate: AnyObject {
func didReceiveResponse(data: Data)
}
class NetworkService {
weak var delegate: NetworkServiceDelegate? // ✅ weak — مندوب جا سکتا ہے
}
مثال میں، Item unowned استعمال کرتا ہے کیونکہ آرڈر آئٹم آرڈر کے بغیر موجود نہیں ہو سکتا — زندگی کی ضمانت پختہ ہے۔ NetworkService weak استعمال کرتا ہے کیونکہ مندوب (مثلاً ViewController) کسی بھی وقت بند اور ختم ہو سکتا ہے۔
کمزور حوالے ایک طاقتور آلہ ہیں، لیکن ان کی حدود ہیں جنہیں iOS ڈویلپمنٹ میں صحیح استعمال کے لیے سمجھنا ضروری ہے۔
کمزور حوالے مضبوط سے سست ہیں: ہر رسائی پر، رن ٹائم چیک کرتا ہے کہ آبجیکٹ ختم ہوا ہے یا نہیں (کمزور جدول میں تلاش)۔ زیادہ تر منظرناموں میں، فرق ناقابل تصور ہے، لیکن لاکھوں رسائیوں والی گرم لوپس میں، weak ایک رکاوٹ بن سکتا ہے۔ زیادہ بوجھ والے منظرناموں کے لیے، strong استعمال کریں اور فن تعمیر کو دوبارہ ترتیب دیں۔
Struct, enum, tuple — قدر کی اقسام جو ARC میں حصہ نہیں لیتیں۔ weak struct اعلان کرنے کی کوشش مرتبی غلطی کا سبب بنتی ہے۔ قدر کی قسم کے لیے کمزور حوالہ ذخیرہ کرنے کے لیے، class قسم میں ایک لپیٹنے والا یا بندش استعمال کریں۔
Zeroing weak تھریڈ محفوظ ہے: اگر ایک آبجیکٹ ایک تھریڈ پر ختم ہوتا ہے، تو کمزور حوالہ تمام تھریڈز پر جوہری طور پر صفر ہو جاتا ہے۔ تاہم، کمزور حوالہ پڑھنے اور اس کا حوالہ کھولنے کے درمیان کی کھڑکی دوڑ کی حالت کا باعث بن سکتی ہے — آبجیکٹ کمزور حوالہ حاصل کرنے اور استعمال کرنے کے درمیان ختم ہو جاتا ہے۔ حل: کمزور حوالہ کو مقامی متغیر میں مضبوط گرفت۔
// متعدد تھریڈنگ میں weak کے ساتھ دوڑ کی حالت
func performAsync() {
weak var weakSelf = self
queue.async {
// ⚠️ weakSelf جانچ اور استعمال کے درمیان nil ہو سکتا ہے
if weakSelf != nil {
weakSelf!.doSomething() // nil ہونے پر CRASH
}
}
}
// ✅ اصلاح: استعمال کے دوران مضبوط گرفت
func performAsyncSafe() {
queue.async { [weak self] in
guard let strongSelf = self else { return }
strongSelf.doSomething() // strongSelf — مقامی مضبوط حوالہ
}
}
محفوظ ورژن میں، weak self کو پکڑا جاتا ہے، پھر فوری طور پر ایک مقامی مضبوط متغیر strongSelf میں کھولا جاتا ہے۔ اگر self اب بھی زندہ ہے، تو یہ بلاک کی مدت تک زندہ رہے گا۔ اگر نہیں، تو guard متحرک ہوتا ہے اور کوڈ عمل نہیں ہوتا۔ یہ محاورہ Swift میں غیر متوازی بندشوں کا معیاری نمونہ ہے۔
IBOutlet Interface Builder میں weak ہونا چاہیے کیونکہ ویو کا درجہ بندی پہلے سے ذیلی ویو پر مضبوط حوالہ رکھتا ہے۔ کنٹرولر میں مضبوط حوالہ کی نقل برقرار رکھنے کا چکر نہیں بناتی لیکن بے کار ہے۔ آؤٹ لیٹ پر کمزور حوالہ Apple کی سفارش ہے، اگرچہ بہت سے ڈویلپر کوڈ کی سادگی کے لیے strong استعمال کرتے ہیں۔
اکثر پوچھے گئے سوالات
نہیں، weak صرف موجودہ آبجیکٹ یا nil کی طرف اشارہ کر سکتا ہے۔ نیا آبجیکٹ بناتے وقت، آپ پہلے ایک مضبوط حوالہ حاصل کرتے ہیں (ایک ابتدائیہ کے ذریعے)، اور اس کے بعد ہی آپ کمزور حوالہ تفویض کر سکتے ہیں۔ شروع میں weak nil ایک عام حالت ہے۔
Weak ARC پر مبنی ہے، جو صرف حوالہ اقسام (classes) کا انتظام کرتا ہے۔ قدر کی اقسام (struct, enum) تفویض پر نقل ہوتی ہیں اور ان کا retain count نہیں ہوتا۔ قدر کی اقسام کے ساتھ کمزور تعلقات کے لیے، weak خصوصیت والے class میں لپیٹنے والے یا بندشیں استعمال کریں۔
کمزور حوالے تک ہر رسائی رن ٹائم جدول میں ایک تلاش کرتی ہے۔ لاکھوں تکرار والی لوپ میں، یہ مضبوط حوالے سے 2–5 گنا سست ہو سکتی ہے۔ گرم راستوں کے لیے، لوپ سے پہلے weak کو مقامی مضبوط متغیر میں کاپی کریں۔
جب آبجیکٹ کے تمام مضبوط حوالے کھو جائیں — دائرہ کار کے آخر میں، کسی خصوصیت کو دوبارہ تفویض کرتے وقت، یا اسکرین بند ہونے پر۔ متعدد تھریڈ والے ماحول میں، یہ کوڈ کی دو سطروں کے درمیان ہو سکتا ہے۔ ہمیشہ guard let یا if let کے ذریعے کمزور حوالوں کی جانچ کریں۔
معنیاتی طور پر ایک جیسے: دونوں zeroing weak فراہم کرتے ہیں۔ فرق: Swift کو اختیاری قسم اور var درکار ہے، Objective-C خصوصیت modifier استعمال کرتا ہے۔ Objective-C __unsafe_unretained بھی سپورٹ کرتا ہے — zeroing کے بغیر کمزور حوالہ (لٹکتے پوائنٹر کا خطرہ)۔
خلاصہ
weak var + اختیاری قسم؛ صرف class اقسام اور AnyObject پروٹوکولہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں