ARC: یہ کیا ہے، iOS میں Automatic Reference Counting کے کام کرنے کا اصول

مصنف: IT Sectr اشاعت: 2026-03-29 مطالعے کا وقت: 8 منٹ

Automatic Reference Counting (ARC) Swift اور Objective-C میں ایک میموری مینجمنٹ سسٹم ہے جو خود بخود ہر آبجیکٹ کے حوالوں کی تعداد شمار کرتا ہے اور کاؤنٹر کے صفر ہونے پر اسے آزاد کر دیتا ہے۔ Apple Swift دستاویز، 2026 کے مطابق، ARC کمپائلر میں شامل ہے اور کمپائلیشن مرحلے پر کام کرتا ہے، صحیح جگہوں پر retain/release کالز داخل کرتا ہے۔ Garbage Collection کے برعکس، ARC کو علیحدہ کلیکٹر تھریڈ کی ضرورت نہیں ہے اور ایپلیکیشن کے عمل کے دوران کوئی وقفہ پیدا نہیں کرتا۔

اہم نکات

  • ARC — Automatic Reference Counting، Swift اور Objective-C میں کمپائلر پر مبنی میموری مینجمنٹ سسٹم
  • کام کرنے کا اصول — ہر آبجیکٹ کا ایک ریفرنس کاؤنٹر (retain count) ہوتا ہے، صفر ہونے پر آبجیکٹ فوری طور پر آزاد ہو جاتا ہے
  • کوالیفائرز — strong، weak اور unowned متعین کرتے ہیں کہ حوالہ کاؤنٹر اور آبجیکٹ کے لائف سائیکل کو کیسے متاثر کرتا ہے
  • GC سے فرق — ARC کمپائلیشن مرحلے پر حتمی طور پر کام کرتا ہے، Stop-The-World وقفوں یا پس منظر کے کلیکٹر تھریڈ کے بغیر
  • Retain Cycle — ARC کا سب سے بڑا مسئلہ: اگر دو آبجیکٹ strong کے ذریعے ایک دوسرے کا حوالہ دیں تو ان کا کاؤنٹر کبھی صفر نہیں ہوتا

ARC کیا ہے؟

ARC (Automatic Reference Counting) ایک کمپائلر پر مبنی میموری مینجمنٹ میکانزم ہے جو Apple نے Xcode 4.2 (2011) میں Objective-C کے لیے متعارف کرایا اور Swift نے اسے وراثت میں لیا۔ دستی میموری مینجمنٹ (Manual Retain-Release، MRR) کے برعکس، ARC retain، release اور autorelease کالز کو مکمل طور پر خودکار بناتا ہے، انہیں ڈویلپر کی مداخلت کے بغیر کمپائلیشن مرحلے پر داخل کرتا ہے۔

ARC کوئی کوڑا کرکٹ جمع کرنے والا نہیں ہے۔ یہ متحرک کوڈ داخل کرنے کے ساتھ جامد تجزیہ ہے: کمپائلر آبجیکٹ کی زندگی کا تجزیہ کرتا ہے اور retain/release کو ان نکات پر رکھتا ہے جہاں آبجیکٹ بنائے جاتے ہیں، کاپی کیے جاتے ہیں یا دائرہ کار سے باہر جاتے ہیں۔ نتیجہ حتمی میموری آزادی ہے: آبجیکٹ بالکل اس وقت ہٹا دیا جاتا ہے جب اس کی طرف کوئی حوالہ نہیں رہتا، بغیر تاخیر یا وقفے کے۔

WWDC 2011 Session 323 کے مطابق، MRR سے ARC میں منتقلی نے Apple ایپلیکیشنز میں میموری سے متعلق کریش بگز کو 70% تک کم کر دیا۔ ڈویلپرز نے دستی طور پر retain/release متوازن کرنا چھوڑ دیا، جس سے لیک اور double-free غلطیوں کی پوری کلاس ختم ہو گئی۔

Automatic Reference Counting کیسے کام کرتا ہے

میموری میں ہر آبجیکٹ کا ایک ریفرنس کاؤنٹر (retain count) ہوتا ہے۔ جب کوئی آبجیکٹ بنایا جاتا ہے، کاؤنٹر 1 پر سیٹ ہوتا ہے۔ جب ایک نیا strong حوالہ آبجیکٹ کی طرف اشارہ کرتا ہے — کاؤنٹر بڑھتا ہے (retain)۔ جب strong حوالہ غائب ہو جاتا ہے — کاؤنٹر گھٹتا ہے (release)۔ صفر تک پہنچنے پر، آبجیکٹ فوری طور پر آزاد ہو جاتا ہے۔

Swift کمپائلر ہر تفویض پر retain/release داخل نہیں کرتا — یہ اصلاح کے لیے جامد تجزیہ استعمال کرتا ہے۔ مثال کے طور پر، اگر کوئی آبجیکٹ منتقل کرنے کے بعد استعمال نہ ہونے کی ضمانت ہو، کمپائلر غیر ضروری release/retain چھوڑ سکتا ہے۔ اس اصلاح کو ARC Optimization کہا جاتا ہے۔

swift
class Person {
    let name: String
    init(name: String) {
        self.name = name
        print("\(name) initialized (retain count: 1)")
    }
    deinit {
        print("\(name) deallocated")
    }
}

func testARC() {
    let p = Person(name: "Alice")  // retain count = 1
    let q = p                      // retain count = 2
    // q دائرہ کار سے باہر جاتا ہے
    // retain count = 1
    // p دائرہ کار سے باہر جاتا ہے
    // retain count = 0 → deinit
}

یہ مثال دکھاتی ہے کہ ARC کاؤنٹر کو کیسے منظم کرتا ہے: q = p تفویض کرنے پر کاؤنٹر بڑھتا ہے؛ q کے دائرہ کار سے باہر جانے پر گھٹتا ہے۔ جب آخری strong حوالہ غائب ہو جاتا ہے، ڈی انیشیالائزر فوری طور پر کال ہوتا ہے۔ کوئی کوڑا کرکٹ جمع کرنے والا انتظار نہیں کرتا — میموری فوری طور پر آزاد ہو جاتی ہے۔

ARC بمقابلہ Garbage Collection: اہم فرق

ARC اور Garbage Collection ایک ہی مسئلہ — خودکار میموری مینجمنٹ — حل کرتے ہیں لیکن بنیادی طور پر مختلف طریقوں سے۔ ان کے درمیان انتخاب زبان کے فن تعمیر کا تعین کرتا ہے: Swift (ARC) بمقابلہ Java/Go (GC)۔ آئیے اہم فرق دیکھتے ہیں۔

خصوصیتARC (Swift/ObjC)GC (Java/Go)
آزادی کا وقتحتمی: کاؤنٹر کے صفر ہوتے ہی فوریغیر حتمی: اگلے جمع کرنے کے چکر میں
عمل میں وقفہکوئی نہیں (retain/release کمپائلیشن پر داخل کردہ)Stop-The-World وقفے (2–200 ms)
اضافی بوجھہر حوالے پر کاؤنٹر میں اضافہ/کمیآبجیکٹ گراف کا چکر، نشان زد کرنا، صاف کرنا
مسائلRetain Cycle (دستی حل)ہیپ کا بکھراؤ، بھولے ہوئے حوالوں سے لیک
اضافی تھریڈضرورت نہیںکوڑا کرکٹ جمع کرنے والے تھریڈ کی ضرورت

اہم سودا: ARC پیش قیاسی آبجیکٹ زندگی اور صفر وقفہ فراہم کرتا ہے، لیکن ڈویلپر سے retain cycles کو سمجھنے اور weak/unowned کا صحیح انتخاب کرنے کی ضرورت ہوتی ہے۔ GC ڈویلپر کو ان پریشانیوں سے آزاد کرتا ہے، لیکن غیر حتمی وقفوں اور ایک اضافی تھریڈ کی قیمت پر۔

Strong، Weak اور Unowned: ARC میں حوالہ کوالیفائرز

ARC تین قسم کے حوالہ کوالیفائرز کی وضاحت کرتا ہے، ہر ایک کاؤنٹر اور آبجیکٹ کی زندگی کے چکر کو مختلف طریقے سے متاثر کرتا ہے۔ صحیح کوالیفائر کا انتخاب Swift میں محفوظ میموری مینجمنٹ کی بنیاد ہے۔

Strong

Strong ڈیفالٹ کوالیفائر ہے۔ ہر strong حوالہ آبجیکٹ کے retain count کو 1 بڑھاتا ہے۔ جب تک کم از کم ایک strong حوالہ موجود ہے، آبجیکٹ زندہ رہتا ہے۔ Swift میں تمام کلاس خصوصیات اور مقامی متغیرات ڈیفالٹ طور پر strong ہیں۔ Strong حوالہ جات ملکیت کا رشتہ بناتے ہیں: آبجیکٹ A، آبجیکٹ B کا مالک ہے۔

Weak

Weak ایک حوالہ ہے جو retain count نہیں بڑھاتا۔ ایک آبجیکٹ آزاد ہو سکتا ہے چاہے weak حوالہ اس کی طرف اشارہ کر رہا ہو۔ آزادی کے بعد، weak حوالہ خود بخود nil پر سیٹ ہو جاتا ہے۔ Weak حوالہ جات ہمیشہ var کے طور پر اختیاری قسم (?) کے ساتھ اعلان کیے جاتے ہیں۔ یہ retain cycles توڑنے کے لیے استعمال ہوتے ہیں، خاص طور پر delegate پیٹرن میں۔

Unowned

Unowned ایک غیر مالک حوالہ ہے، جو weak کی طرح retain count نہیں بڑھاتا۔ تاہم، unowned حوالہ آزادی کے بعد nil پر سیٹ نہیں ہوتا — آزاد شدہ آبجیکٹ تک رسائی کریش کا سبب بنتی ہے۔ Unowned اس وقت استعمال ہوتا ہے جب ضمانت ہو کہ آبجیکٹ کم از کم حوالہ لینے والے آبجیکٹ جتنا زندہ رہتا ہے۔ عام استعمال کے کیسز closures اور ضمانتی زندگی کے ساتھ والدین-بچے کے تعلقات ہیں۔

swift
class Customer {
    let name: String
    var card: CreditCard?         // strong
    init(name: String) { self.name = name }
    deinit { print("\(name) deallocated") }
}

class CreditCard {
    let number: String
    unowned let customer: Customer   // unowned — مالک نہیں
    init(number: String, customer: Customer) {
        self.number = number
        self.customer = customer
    }
    deinit { print("Card \(number) deallocated") }
}

var customer: Customer? = Customer(name: "Bob")
customer?.card = CreditCard(number: "1234", customer: customer!)
customer = nil
// Customer اور CreditCard دونوں آزاد — کوئی retain cycle نہیں

یہاں CreditCard Customer کے لیے unowned حوالہ استعمال کرتا ہے۔ Customer کارڈ کا مالک ہے (strong)، اور کارڈ گاہک کا مالک نہیں ہے (unowned)۔ جب Customer آزاد ہوتا ہے، دونوں آبجیکٹ آزاد ہو جاتے ہیں — کوئی retain cycle نہیں ہوتا۔ اگر card.customer strong ہوتا، تو چکر آزادی کو روک دیتا۔

ARC کے عام مسائل اور ان کے حل

آٹومیشن کے باوجود، ARC کوئی علاج نہیں ہے۔ ڈویلپرز کو کئی عام مسائل کا سامنا کرنا پڑتا ہے جن کے لیے اندرونی میموری مینجمنٹ میکانزم کی سمجھ کی ضرورت ہوتی ہے۔

Closures میں Retain Cycle

Swift میں closures بیرونی متغیرات کو strong حوالہ سے پکڑتے ہیں۔ اگر ایک closure کسی کلاس خصوصیت کو تفویض کیا جائے اور self کو پکڑے — ایک retain cycle پیدا ہوتا ہے: کلاس closure کو رکھتی ہے، closure self کو رکھتا ہے۔ حل weak یا unowned کے ساتھ کیپچر لسٹ ہے۔

swift
class NetworkManager {
    var completionHandler: ((Data?) -> Void)?
    var data: Data?

    func fetchData() {
        completionHandler = { [weak self] result in
            guard let self else { return }
            self.data = result
            self.processResult()
        }
    }

    func processResult() { }
}

کیپچر لسٹ [weak self] closure کے اندر self کے لیے weak حوالہ بناتی ہے۔ یہ ممکنہ retain cycle کو توڑتا ہے۔ Guard let self کوڈ چلانے سے پہلے آبجیکٹ کے زندہ ہونے کی ضمانت دیتا ہے۔ weak self Swift میں غیر متزامن closures کے لیے معیاری عمل ہے۔

Retain/Release کارکردگی

اگرچہ retain/release ہلکی کارروائیاں ہیں، گرم لوپ میں بار بار کاؤنٹر میں اضافہ/کمی اضافی بوجھ ڈالتا ہے۔ Swift 5.9+ میں، کمپائلر اصلاح استعمال کرتا ہے جو بے کار retain/release کو ہٹا دیتا ہے اگر تجزیہ کار اسے محفوظ ثابت کرے۔ تاہم، Objective-C میں، retain/release فی سیکنڈ لاکھوں کالوں والے زیادہ بوجھ کے منظرناموں میں رکاوٹ بن سکتے ہیں۔

Autorelease Pool

Autorelease Pool ایک التوا والی رہائی کا میکانزم ہے جو Objective-C اور کچھ Swift منظرناموں میں استعمال ہوتا ہے۔ آبجیکٹ کو پول میں رکھا جاتا ہے اور پول کے خالی ہونے پر release ملتا ہے۔ بہت سے عارضی آبجیکٹ (مثلاً JSON پارسنگ) والے لوپ میں، حسب ضرورت autoreleasepool بنانے سے چوٹی میموری کی کھپت کم ہوتی ہے۔

اکثر پوچھے گئے سوالات

ARC دستی میموری مینجمنٹ (MRR) سے کیسے مختلف ہے؟

دستی مینجمنٹ (MRR) میں، ڈویلپر واضح طور پر retain، release اور autorelease کال کرتا تھا۔ ARC ان کالوں کو کمپائلیشن مرحلے پر خود بخود داخل کرتا ہے، double-free کے خطرے، بھولے ہوئے release سے لیک اور retain/release توازن کی غلطیوں کو ختم کرتا ہے۔

کیا ARC C/C++ کوڈ کے ساتھ کام کر سکتا ہے؟

ARC صرف Objective-C آبجیکٹ اور Swift کلاسز کا انتظام کرتا ہے۔ C/C++ ڈھانچوں اور پوائنٹرز کے لیے ARC لاگو نہیں ہوتا — یہ آبجیکٹ دستی طور پر یا C++ سمارٹ پوائنٹرز (shared_ptr, unique_ptr) کے ذریعے منظم کیے جاتے ہیں۔ Core Foundation آبجیکٹ (CFString, CGColor) بھی ARC کے دائرہ کار میں نہیں آتے۔

کب weak اور کب unowned استعمال کریں؟

weak — جب آبجیکٹ حوالہ لینے والے آبجیکٹ سے پہلے آزاد ہو سکتا ہے (نمائندگان، غیر متزامن closures)۔ unowned — جب ضمانت ہو کہ آبجیکٹ کم از کم حوالہ لینے والے جتنا زندہ رہتا ہے (والدین-بچے جہاں بچہ والدین کے بغیر موجود نہیں رہ سکتا)۔ یقین نہ ہو تو weak منتخب کریں۔

وجودی اقسام (Existential Types) کیا ہیں اور وہ ARC کو کیسے متاثر کرتی ہیں؟

Swift میں وجودی اقسام (protocol بطور قسم) قدر کو ایک خاص کنٹینر (existential container) میں لپیٹتی ہیں۔ یہ پروٹوکول حدود پر retain/release کی تعداد بڑھاتا ہے۔ Swift 5.7+ میں، غیر شفاف نتیجہ کی اقسام (opaque result types) اور some پیرامیٹرز کنٹینر کو ہٹا کر اضافی بوجھ کم کرتے ہیں۔

Swift میں retain count کیسے چیک کریں؟

Swift میں retain count پڑھنے کے لیے کوئی براہ راست API نہیں ہے — اسے نفاذ کی تفصیل سمجھا جاتا ہے۔ تشخیص کے لیے، Xcode میں Instruments (Allocations, Leaks) یا میموری ڈیبگر استعمال کریں۔ یہ اوزار زندہ کلاس مثالوں کی تعداد اور برقرار رکھنے کی زنجیریں دکھاتے ہیں۔

خلاصہ

  • ARC — Swift اور Objective-C کے لیے کمپائلر پر مبنی میموری مینجمنٹ سسٹم جو حوالہ گنتی کے ذریعے کام کرتا ہے
  • اصول — ہر آبجیکٹ کا retain count ہوتا ہے؛ صفر ہونے پر آبجیکٹ فوری طور پر اور حتمی طور پر آزاد ہوتا ہے
  • GC سے فرق — ARC پس منظر کے تھریڈ یا Stop-The-World وقفوں کے بغیر کام کرتا ہے، لیکن retain cycles کے کنٹرول کی ضرورت ہے
  • Strong — کاؤنٹر بڑھاتا ہے؛ weak اور unowned نہیں بڑھاتے، لیکن unowned آزادی پر nil نہیں ہوتا
  • Closures — Swift میں retain cycles کی بنیادی وجہ؛ [weak self] کیپچر لسٹ معیاری حل ہے
  • Autorelease Pool — لوپ اور حسب ضرورت منظرناموں میں عارضی آبجیکٹ کے لیے التوا والی رہائی کا میکانزم
  • تشخیص — Xcode میموری ڈیبگر، Instruments اور LeakCanary (ObjC برج کے ذریعے) مسائل تلاش کرنے کے لیے

ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے

IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔

پروجیکٹ پر بحث کریں

مزید پڑھیں