ARC: nədir, Automatic Reference Counting-in iOS-da iş prinsipi

Müəllif: IT Sectr Dərc olunub: 2026-03-29 Oxuma vaxtı: 8 dəq

Automatic Reference Counting (ARC) — Swift və Objective-C-də yaddaşı idarəetmə sistemidir, hər bir obyektə olan referansların sayını avtomatik hesablayır və sayı sıfıra çatdıqda onu azad edir. Apple Swift Documentation, 2026-ya görə, ARC kompilyatora daxil edilib və kompilyasiya mərhələsində işləyir, lazımi yerlərdə retain/release çağırışlarını yerləşdirir. Garbage Collection-dan fərqli olaraq, ARC ayrıca toplayıcı ipi tələb etmir və tətbiqin icrası zamanı fasilələr yaratmır.

Əsas məqamlar

  • ARC — Automatic Reference Counting, Swift və Objective-C-də kompilyator yaddaş idarəetmə sistemi
  • İş prinsipi — hər bir obyektin referans sayı (retain count) var, sıfırlandıqda obyekt dərhal azad edilir
  • Kvalifikatorlar — strong, weak və unowned referansın sayına və obyektin həyat dövrünə necə təsir etdiyini müəyyənləşdirir
  • GC-dən fərqi — ARC kompilyasiya mərhələsində deterministik işləyir, Stop-The-World fasilələri və toplayıcı fon ipi olmadan
  • Retain Cycle — ARC-nin əsas problemi: iki obyekt strong vasitəsilə bir-birinə istinad edirsə, onların sayı heç vaxt sıfıra enmir

ARC nədir?

ARC (Automatic Reference Counting) — Apple tərəfindən Xcode 4.2-də (2011) Objective-C üçün təqdim edilmiş və Swift tərəfindən miras alınmış kompilyator yaddaş idarəetmə mexanizmidir. Manual Retain-Release (MRR)-dən fərqli olaraq, ARC retain, release və autorelease çağırışlarını tam avtomatlaşdırır, onları kompilyasiya mərhələsində proqramçının iştirakı olmadan yerləşdirir.

ARC garbage collector deyil. Bu, dinamik kod yerləşdirmə ilə statik analizdir: kompilyator obyektlərin ömür müddətini təhlil edir və obyektlərin yaradıldığı, kopyalandığı və ya görünüş dairəsindən çıxdığı nöqtələrdə retain/release yerləşdirir. Nəticə — deterministik yaddaş boşaldılması: obyekt ona istinadlar dayandıqda dəqiq həmin anda, gecikmələr və fasilələr olmadan silinir.

WWDC 2011 Session 323-yə görə, MRR-dən ARC-yə keçid Apple tətbiqlərində yaddaşla bağlı crash-buqların sayını 70% azaldıb. Proqramçılar əl ilə retain/release balanslaşdırmağı dayandırdılar, bu da bütöv bir sınıf sızıntı və double-free səhvlərini aradan qaldırdı.

Automatic Reference Counting necə işləyir

Yaddaşdakı hər bir obyektin referans sayı (retain count) var. Obyekt yaradıldıqda say 1 olaraq təyin edilir. Yeni strong-referans obyektə istinad etdikdə say artır (retain). Strong-referans yox olduqda say azalır (release). Sıfıra çatdıqda obyekt dərhal dealokasiya edilir.

Swift kompilyatoru retain/release-i hər təyinata deyil — optimallaşdırma üçün statik analizdən istifadə edir. Məsələn, əgər obyekt ötürüldükdən sonra istifadə edilməyəcəksə, kompilyator artıq release/retain-i buraxa bilər. Bu optimallaşdırmaya ARC Optimisation deyilir.

swift
class Person {
    let name: String
    init(name: String) {
        self.name = name
        print("\(name) işə salındı (retain count: 1)")
    }
    deinit {
        print("\(name) dealokasiya edildi")
    }
}

func testARC() {
    let p = Person(name: "Alice")  // retain count = 1
    let q = p                      // retain count = 2
    // q görünüş dairəsindən çıxır
    // retain count = 1
    // p görünüş dairəsindən çıxır
    // retain count = 0 → deinit
}

Bu nümunədə ARC-nin sayı necə idarə etdiyi görünür: q = p təyin edildikdə say artır, q görünüş dairəsindən çıxdıqda azalır. Son strong-referans yox olduqda deinicializator dərhal çağırılır. Heç bir garbage collector gözləmir — yaddaş dərhal azad edilir.

ARC vs Garbage Collection: əsas fərqlər

ARC və Garbage Collection eyni vəzifəni — avtomatik yaddaş idarəetməni — həll edir, lakin prinsipial olaraq fərqli yanaşmalarla. Onlar arasındakı seçim dilin arxitekturasını müəyyənləşdirir: Swift (ARC) vs Java/Go (GC). Əsas fərqləri nəzərdən keçirək.

XüsusiyyətARC (Swift/ObjC)GC (Java/Go)
Boşaltma anıDeterministik: say sıfırlandıqda dərhalQeyri-deterministik: növbəti yığımda
İcra fasilələriYoxdur (kompilyasiya mərhələsində retain/release əlavələri)Stop-The-World fasilələri var (2–200 ms)
Əlavə yükHər referansda sayın artırılması/azaldılmasıObyekt qrafının gəzilməsi, işaretləmə, təmizləmə
ProblemlərRetain Cycle (əl ilə həll)Heap fraqmentasiyası, unudulmuş referanslarda sızıntılar
Əlavə ipTələb olunmurGarbage collector ipi tələb olunur

Əsas kompromis: ARC obyektlərin proqnozlaşdırıla bilən ömür müddətini və sıfır fasilələri təmin edir, lakin proqramçıdan retain cycle anlayışı və düzgün weak/unowned seçimi tələb edir. GC bu narahatlıqlardan azad edir, lakin qeyri-deterministik fasilələr və əlavə ip bahasına.

Strong, Weak və Unowned: ARC-də referans kvalifikatorları

ARC üç növ referans kvalifikatoru təyin edir, onların hər biri sayı və obyektin həyat dövrünü fərqli şəkildə təsir edir. Kvalifikatorun düzgün seçimi Swift-də təhlükəsiz yaddaş işinin əsasıdır.

Strong

Strong — standart kvalifikator. Hər bir strong-referans obyektin retain count-nu 1 artırır. Heç olmasa bir strong-referans mövcud olduğu müddətdə obyekt yaşayır. Swift-də sinif xüsusiyyətləri və lokal dəyişənlər standart olaraq strong-dur. Strong-referanslar sahiblik münasibəti yaradır: A obyekti B obyektinə sahibdir.

Weak

Weak — retain count-u artırmayan referansdır. Obyekt weak-referans ona istinad etsə belə dealokasiya edilə bilər. Dealokasiyadan sonra weak-referans avtomatik olaraq nil olaraq təyin edilir. Weak-referanslar həmişə isteğçi tiplə (?) var kimi bəyan edilir. Onlar retain cycle-ı qırmaq üçün, xüsusilə delegate nümunəsində istifadə olunur.

Unowned

Unowned — weak kimi retain count-u artırmayan sahib olmayan referansdır. Lakin unowned-referans dealokasiyadan sonra nil olaraq təyin edilmir — azad edilmiş obyektə müraciət crash-a səbəb olur. Unowned obyektin referans edən obyektdən azı qədər yaşayacağı təmin edildikdə istifadə olunur. Tipik ssenari — qapanmalar (closures) və təmin edilmiş ömür müddəti ilə valideyn-uşaq münasibətləri.

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

class CreditCard {
    let number: String
    unowned let customer: Customer   // unowned — sahib deyil
    init(number: String, customer: Customer) {
        self.number = number
        self.customer = customer
    }
    deinit { print("Kart \(number) dealokasiya edildi") }
}

var customer: Customer? = Customer(name: "Bob")
customer?.card = CreditCard(number: "1234", customer: customer!)
customer = nil
// Customer və CreditCard hər ikisi azad edildi — retain cycle yoxdur

Burada CreditCard Customer-ə unowned-referansdan istifadə edir. Customer karta sahibdir (strong), karta isə müştəriyə sahib deyil (unowned). Customer nil olduqda hər iki obyekt azad edilir — retain cycle yaranmır. Əgər card.customer strong olsaydı, dövrü azad olmağı bloklayardı.

ARC-nin tipik problemləri və həll yolları

Avtomatlaşdırmaya baxmayaraq, ARC panacea deyil. Proqramçılar yaddaş idarəetmə mexanizmini anlamağı tələb edən bir neçə tipik problemlə qarşılaşırlar.

Qapanmalarda Retain Cycle

Swift-də qapanmalar (closures) xarici dəyişənləri strong-referansla tutur. Əgər qapanma sinifin xüsusiyyətinə təyin edilirsə və self-i tutursa — retain cycle yaranır: sinif qapanmanı, qapanma self-i saxlayır. Həll — weak və ya unowned ilə capture list.

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() { }
}

Capture list [weak self] qapanma daxilində self-ə weak-referans yaradır. Bu potensial retain cycle-ı qırır. Guard let self kodu icra etməzdən əvvəl obyektin canlı olduğunu təmin edir. weak self — Swift-də asinxron qapanmalar üçün standart təcrübədir.

Retain/Release performansı

Retain/release yüngül əməliyyatlar olsa da, isti dövrülərdə tez-tez say artırılması/azaldılması əlavə yük yaradır. Swift 5.9+-da kompilyator optimallaşdırma istifadə edir, burada analizator təhlükəsizliyi sübut edərsə, artıq retain/release-lər silinir. Bununla belə, Objective-C-də retain/release saniyədə milyonlarla çağırışlı yüksək yüklü ssenarilərdə hələ də darboğaz ola bilər.

Autorelease Pool

Autorelease Pool — Objective-C və Swift-in bəzi ssenarilərində istifadə olunan gecikdirilmiş release mexanizmidir. Obyektlər hovuza yerləşdirilir və hovuz boşaldıldıqda release alır. Çox sayda müvəqqəti obyekti olan dövrülərdə (məsələn, JSON parse etmə) öz autoreleasepool yaratmaq operativ yaddaşın pik istehlakını azaldır.

Tez-tez verilən suallar

ARC əl ilə yaddaş idarəetmədən (MRR) nə ilə fərqlənir?

Əl ilə idarəetmədə (MRR) proqramçı açıq şəkildə retain, release və autorelease çağırırdı. ARC bu çağırışları kompilyasiya mərhələsində avtomatik yerləşdirir, double-free riskini, unudulmuş release səbəbindən sızıntıları və retain/release balanslaşdırma səhvlərini aradan qaldırır.

ARC C/C++ kodu ilə işləyə bilər?

ARC yalnız Objective-C obyektləri və Swift class-larını idarə edir. C/C++ strukturları və göstəriciləri üçün ARC tətbiq edilmir — bu obyektlər əl ilə və ya C++ ağıllı göstəriciləri (shared_ptr, unique_ptr) vasitəsilə idarə olunur. Core Foundation obyektləri (CFString, CGColor) də ARC-yə daxil deyil.

Nə vaxt weak, nə vaxt unowned istifadə etməli?

weak — obyekt referans edəndən daha tez dealokasiya edilə bildikdə (delegatlar, asinxron qapanmalar). unowned — obyektin referans edəndən az olmayaraq yaşayacağı təmin edildikdə (valideyn-uşaq, uşaq valideyn olmadan mövcud ola bilməz). Əgər əminsinizsə — weak seçin.

Ekzistensial tiplər nədir və onlar ARC-yə necə təsir edir?

Swift-də ekzistensial tiplər (protocol as type) dəyəri xüsusi konteynerə (existential container) yığır. Bu, protokol sərhədlərində retain/release sayını artırır. Swift 5.7+-da opaque result types və some parametrləri konteyneri aradan qaldıraraq əlavə yükü azaldır.

Swift-də retain count-u necə yoxlamaq olar?

Swift-də retain count-u oxumaq üçün birbaşa API yoxdur — bu tətbiq detayı hesab olunur. Diaqnostika üçün Xcode-da Instruments (Allocations, Leaks) və ya Memory Debugger istifadə edin. Bu alətlər sinfin canlı instansiyalarının sayını və saxlama zəncirini göstərir.

Nəticə

  • ARC — Swift və Objective-C üçün referans sayına əsaslanan kompilyator yaddaş idarəetmə sistemi
  • Prinsip — hər obyektin retain count-u var; sıfırlandıqda obyekt dərhal və deterministik şəkildə azad edilir
  • GC-dən fərqi — ARC fon ipi və Stop-The-World fasilələri olmadan işləyir, lakin retain cycle nəzarəti tələb edir
  • Strong — sayı artırır; weak və unowned — artırmır, lakin unowned dealokasiyada sıfırlanmır
  • Qapanmalar — Swift-də retain cycle-ın əsas səbəbi; capture list [weak self] — standart həll
  • Autorelease Pool — dövrülərdə və xüsusi ssenarilərdə müvəqqəti obyektlər üçün gecikdirilmiş boşaltma mexanizmi
  • Diaqnostika — Xcode Memory Debugger, Instruments və LeakCanary (ObjC bridge vasitəsilə) problemlərin aşkar edilməsi üçün

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun