Weak Reference — bu nədir, sintaksisi və mobil inkişafda tətbiqi

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

Weak Reference (zəif istinad) — ARC-də obyektin saxlama sayğacını artırmayan istinaddır. Apple Swift Language Guide, 2026-ya görə, weak-istinadlar weak açar sözü ilə elan edilir və həmişə opsional tipə malikdir. Obyekt sərbəst buraxıldıqda, ona olan bütün weak-istinadlar avtomatik olaraq nil-ə təyin edilir ki, bu da asılı göstəricilərin qarşısını alır və zəif istinadları retain cycle-ı qırmaq üçün təhlükəsiz mexanizm edir.

Əsas

  • Weak Reference — obyektin retain count-na təsir etməyən istinad; obyekt sərbəst buraxıldıqda sıfırlanır
  • Bəyannamə — var qabağında weak açar sözü; tip həmişə opsionaldır (?)
  • Tətbiq — delegate-lər, closure-lar, parent-child münasibətləri retain cycle-ı qırmaq üçün
  • Təhlükəsizlik — obyektin deallokasiyasından sonra avtomatik nil-ə təyin (zeroing weak)
  • Unowned-dan fərqi — weak sıfırlanır və təhlükəsizdir, unowned sıfırlanmır və ömür qarantiyası tələb edir

Weak Reference nədir?

Weak Reference — ARC-də (Automatic Reference Counting) obyektə sahib olmayan istinaddır. Obyektin retain count-nı artıran və onun həyatını qarantiyalayan strong-istinaddan fərqli olaraq, weak-istinad obyektin hələ də istinadlar olsa belə sərbəst buraxılmasına imkan verir. Sərbəst buraxıldıqdan sonra weak-istinad avtomatik olaraq nil-ə təyin edilir — bu zeroing weak adlanır.

Zeroing weak — Swift və Objective-C runtime-ının əsas xüsusiyyətidir. Obyektin istinad sayğacı sıfıra çatdıqda və obyekt deallokasiya edildikdə, runtime bu obyektə olan bütün weak-istinadları (xüsusi weak-cədvəlində saxlanılır) gəzir və onları nil-ə təyin edir. Bu, weak-istinadlar vasitəsilə sərbəst buraxılmış yaddaşa müraciətin (use-after-free) qeyri-mümkün olmasını təmin edir — istənilən oxuma nil qaytarır.

Apple WWDC 2012 Session 406-ya görə, zeroing weak istinadlar əl ilə yaddaş idarəçiliyində (MRR) geniş yayılmış asılı göstəricilərlə (dangling pointers) bağlı crash səhvlərinin bütün sinfini aradan qaldırdı. MRR-də zəif istinadlar yalnız __unsafe_unretained kimi mövcud idi — onlar sıfırlanmırdı və sərbəst buraxılmış obyektə müraciət EXC_BAD_ACCESS-ə səbəb olurdu.

Swift və Objective-C-də weak sintaksisi

Apple ekosisteminin hər iki dilində weak-istinadların elan sintaksisinə baxaq. Ümumi runtime-a baxmayaraq, sintaksis fərqlənir, lakin semantika eynidir.

Swift

Swift-də weak-istinadlar var qabağında weak açar sözü ilə elan edilir. Tip həmişə opsional olmalıdır (Type?), çünki istinad istənilən anda sıfırlana bilər. Sabitlər (let) weak ola bilməz — yalnız dəyişənlər.

swift
class ViewController: UIViewController {
    // weak-xüsusiyyətlər: yalnız var, yalnız optional
    weak var delegate: ViewControllerDelegate?
    weak var parentView: UIView?

    weak var completionHandler: ((Bool) -> Void)?  // ⚠️ closure-lar weak saxlamır
    // ⬆️ Xəta: weak yalnız class-tipi üçün tətbiq edilə bilər, closure üçün deyil
}

Vacib: weak yalnız sinif nümunələrinə (class-types), AnyObject-ə və AnyObject-dən miras alan protokollara tətbiq oluna bilər. Struct, enum və closure weak ola bilməz — onlar dəyər tipləridir və ARC-də iştirak etmirlər.

Objective-C

Objective-C-də weak-xüsusiyyətlər __weak atributu və ya property-də weak modifikatoru ilə elan edilir:

objective-c
// Objective-C: weak property
@interface MyViewController : UIViewController
@property (weak, nonatomic) id<MyDelegate> delegate;
@end

// Lokal weak-dəyişən
__weak MyObject *weakRef = someStrongObject;

Objective-C runtime da zeroing weak təmin edir, lakin əlavə olaraq weak-in C-strukturları və bəzi Core Foundation obyektləri ilə istifadəsini bloklayır. Onlar üçün __unsafe_unretained tətbiq edilir — zeroing olmadan.

Zəif istinadları nə vaxt tətbiq etməli

Zəif istinadlar — universal həll deyil, konkret ssenarilər üçün alətdir. Hər yerdə weak istifadə etmək həddindən artıq mürəkkəbliyə gətirib çıxarır və oxunaqlılığı pisləşdirir. Düzgün tətbiq ssenarilərinə baxaq.

Delegatlar (Delegate pattern)

Delegat — weak üçün əsas ssenari. Sahib-obyekt (məsələn, UITableView) özündə strong-istinad saxlayır, delegat (UIViewController) isə cədvələ sahib olmamalıdır. Apple SDK bütün delegate və dataSource-ların weak olmasını təmin edir. Öz protokollarınız üçün həmişə weak var delegate istifadə edin.

Parent-Child əks əlaqə ilə

Uşaq obyekt valideynə istinad etməli olduqda (məsələn, ChildViewController koordinatora giriş üçün), weak-istinaddan istifadə edin. Valideyn uşağa sahibdir (strong), uşaq valideyni müşahidə edir (weak) — retain cycle istisna edilir.

Asinxron closure-lar

Capture list [weak self] — sinifin xüsusiyyətləri kimi saxlanılan closure-larda retain cycle-dan qaçmağın standart üsuludur. Əgər self closure tamamlanmazdan əvvəl sərbəst buraxıla bilərsə — weak self məcburidir.

SsenariWeakStrong
Delegate✅ Həmişə weak❌ Retain cycle
Parent → Child❌ Lazım deyil (valideyn sahib olmalıdır)✅ Strong
Child → Parent✅ Weak❌ Retain cycle
Asinxron callback✅ [weak self]❌ Retain cycle riski
Güclü əlaqə (owned)❌ unowned✅ Strong

Ümumi qayda: əgər A obyekti B-yə sahibdirsə (A → B strong), onda B → A weak və ya unowned olmalıdır. Strong-istinadların istiqaməti həmişə sahibdən tabe olana doğru olmalıdır.

Weak vs Unowned: müqayisə və ssenarilər

Həm weak, həm də unowned retain count-nı artırmır, lakin obyektin deallokasiyasından sonra davranışları fərqlənir. Onlar arasında seçim ömür qarantiyaları məsələsidir.

Fərqlər

Weak: avtomatik sıfırlanır (nil), tip həmişə optionaldır, istifadədən əvvəl unwrap tələb edir. Təhlükəsizdir — nil-ə müraciət crash-a səbəb olmur.

Unowned: sıfırlanmır, tip non-optionaldır. Əgər obyekt sərbəst buraxılıbsa, unowned-istinad asılı göstəriciyə çevrilir — ona müraciət runtime crash-na səbəb olur. Unowned obyektin istinad edən tərəfdən az yaşamadığını qəbul edir.

Nə vaxt weak seçməli

Weak seçin, əgər: obyekt istənilən anda deallokasiya edilə bilərsə (ekran bağlandıqdan sonra delegat), obyektin ömrünü idarə etmirsinizsə və ya qarantiyalara şübhə edirsinizsə. Weak — universal təhlükəsiz seçimdir.

Nə vaxt unowned seçməli

Unowned seçin, əgər: obyekt qarantiyalı olaraq istinad edəndən əvvəl sərbəst buraxıla bilməz (məsələn, Customer → CreditCard, burada kart müştərisiz mövcud deyil). Unowned unwrap olmadan non-optional API verir ki, bu da kodda daha rahatdır.

swift
class Order {
    let id: Int
    var items: [Item] = []

    init(id: Int) { self.id = id }

    // Güclü əlaqə: Order Item-ə sahibdir
    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 olmadan yaşamır

    init(name: String, order: Order) {
        self.name = name
        self.order = order
    }
}

// Weak ilə nümunə: ömür qarantiyası olmayan delegat
protocol NetworkServiceDelegate: AnyObject {
    func didReceiveResponse(data: Data)
}

class NetworkService {
    weak var delegate: NetworkServiceDelegate?  // ✅ weak — delegat gedə bilər
}

Nümunədə Item unowned istifadə edir, çünki sifariş elementi sifarişin özü olmadan mövcud ola bilməz — ömür qarantiyası dəmir-betondur. NetworkService weak istifadə edir, çünki delegat (məsələn, ViewController) istənilən anda bağlana və sərbəst buraxıla bilər.

Zəif istinadların məhdudiyyətləri və tələlər

Zəif istinadlar — güclü alətdir, lakin iOS inkişafında düzgün tətbiq üçün başa düşülməsi vacib olan məhdudiyyətləri var.

Weak performansı

Zəif istinadlar strong-dan yavaşdır: hər girişdə runtime obyektin sərbəst buraxılıb-buraxılmadığını yoxlayır (weak-cədvəlində lookup). Ssenarilərin böyük əksəriyyətində fərq hiss olunmur, lakin milyonlarla müraciəti olan isti dövrələrdə weak darboğaz ola bilər. Yüksək yüklü ssenarilər üçün strong istifadə edin və arxitekturanı yenidən təşkil edin.

Weak dəyər tiplərinə tətbiq edilmir

Struct, enum, tuple — ARC-də iştirak etməyən dəyər tipləridir. Weak struct elan etmək cəhdi kompilasiya xətasına səbəb olur. Dəyər tipinə zəif istinad saxlamaq üçün class tipində qablaşdırma və ya closure istifadə edin.

Weak çoxipliklikdə

Zeroing weak ip-saxlayıcıdır: əgər obyekt bir ipdə sərbəst buraxılırsa, weak-istinad bütün iplərdə atomik olaraq sıfırlanır. Lakin weak-istinadın oxunması ilə ondan istifadə arasındakı fasilə yarış vəziyyətinə səbəb ola bilər — obyekt weak-istinadın alınması ilə istifadəsi arasında sərbəst buraxılır. Həll yolu: zəif istinadın strong-tutulması lokal dəyişənə.

swift
// Weak ilə çoxiplikdə race condition
func performAsync() {
    weak var weakSelf = self
    queue.async {
        // ⚠️ weakSelf yoxlama və istifadə arasında nil ola bilər
        if weakSelf != nil {
            weakSelf!.doSomething()  // CRASH əgər nil oldusa
        }
    }
}

// ✅ Düzəliş: istifadə müddətinə güclü tutma
func performAsyncSafe() {
    queue.async { [weak self] in
        guard let strongSelf = self else { return }
        strongSelf.doSomething()  // strongSelf — lokal strong-istinad
    }
}

Təhlükəsiz variantda weak self tutulur, sonra dərhal lokal strong-dəyişənə strongSelf açılır. Əgər self hələ də yaşayırsa — blokun icrası müddətində yaşamağa davam edəcək. Əgər yoxsa — guard işə düşür və kod icra olunmur. Bu idiom — Swift-də asinxron closure-lar üçün standart nümunədir.

UIView və weak outlet

IBOutlet Interface Builder-də weak olmalıdır, çünki görünüş hiyerarxiyası artıq subview-da strong-istinad saxlayır. Kontrollerdə strong-istinadın təkrarlanması retain cycle yaratmır, lakin artıqdır. Outlet-ə zəif istinad — Apple tövsiyəsidir, baxmayaraq ki, bir çox proqramçı kodu sadələşdirmək üçün strong istifadə edir.

Tez-tez verilən suallar

Weak-istinad hələ yaradılmamış obyektə işarə edə bilərmi?

Xeyr, weak yalnız mövcud obyektə və ya nil-ə işarə edə bilər. Yeni obyekt yaratdıqda əvvəlcə strong-istinad alırsınız (inicializator vasitəsilə), və yalnız bundan sonra zəif istinad təyin edə bilərsiniz. Əvvəldə weak nil — normal haldır.

Niyə weak yalnız class-tipləri ilə işləyir?

Weak yalnız referans tiplərini (siniflər) idarə edən ARC-ə əsaslanır. Dəyər tipləri (struct, enum) təyin edilərkən kopyalanır və retain count-a malik deyil. Dəyər tiplərinin zəif əlaqəsi üçün closure-lar və ya weak-xüsusiyyətli class qablaşdırmasından istifadə edin.

Weak dövrədə performansa necə təsir edir?

Weak-istinada hər giriş runtime-cədvəlində lookup yerinə yetirir. Milyonlarla iterasiyası olan dövrədə bu strong-istinaddan 2–5 dəfə yavaş ola bilər. İsti yollar üçün weak-i dövrədən əvvəl lokal strong-dəyişənə kopyalayın.

Weak-istinad nə vaxt gözlənilmədən nil ola bilər?

Obyektə olan bütün strong-istinadlar itirildikdə — skopun sonunda, xüsusiyyət yenidən təyin edilərkən, ekran bağlandıqda. Çoxiplik mühitində bu iki kod sətri arasında baş verə bilər. Həmişə weak-i guard let və ya if let vasitəsilə yoxlayın.

Weak Objective-C-dəki __weak-dən nə ilə fərqlənir?

Semantik olaraq eynidir: hər ikisi zeroing weak təmin edir. Fərqlər: Swift optional-tip və var tələb edir, Objective-C property modifikatorundan istifadə edir. Objective-C həmçinin __unsafe_unretained-i dəstəkləyir — zeroing olmadan zəif istinad (asılı göstərici riski).

Nəticə

  • Weak Reference — sahib olmayan, retain count-nı artırmayan və deallokasiyada avtomatik sıfırlanan istinad
  • Sintaksisweak var + opsional tip; yalnız class-tipləri və AnyObject protokolları
  • Zeroing weak — runtime sərbəst buraxılmış obyektə bütün weak-istinadları sıfırlayır, asılı göstəricilərin qarşısını alır
  • Ssenarilər — delegate-lər, parent-child əks əlaqə ilə, asinxron closure-lar ([weak self])
  • Weak vs Unowned — weak sıfırlanır (təhlükəsiz), unowned sıfırlanmır (crash riski, lakin non-optional)
  • Performans — weak runtime-cədvəlində lookup səbəbindən strong-dan yavaşdır; isti yollar üçün strong-a kopyalayın
  • Tövsiyə — ömür qarantiyalarına əmin deyilsinizsə — weak seçin

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