iOS-də tutma dövrləri (retain cycles) nədir?
sobes.tech Süni İntellekt
AI-dan cavab
Qarşılıqlı əlaqəli iki və ya daha çox obyektin güclü istinadlara malik olması nəticəsində "dairəvi əlaqə" yaranır. Bu zaman hər bir obyektin istinad sayğacı sıfıra çatmır və ARC (Avtomatik İstinad Sayğacı) tərəfindən sərbəst buraxıla bilməz. Bu, yaddaş sızmalarına səbəb olur, çünki obyektlər istifadə olunmasa belə yaddaşda qalır.
Misal:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
print("\(name) initialize olunur")
}
deinit {
print("\(name) sərbəst buraxılır")
}
}
class Apartment {
let unit: String
var tenant: Person?
init(unit: String) {
self.unit = unit
print("Apartment \(unit) initialize olunur")
}
deinit {
print("Apartment \(unit) sərbəst buraxılır")
}
}
Bu nümunədə, əgər Person obyektinin güclü istinadı Apartment-a və Apartment-in güclü istinadı Person-a olsa, bu obyektlər sərbəst buraxılmağa çalışıldıqda, onlar silinməz, çünki onların istinad sayğacı sıfıra çatmır.
Qarşılıqlı əlaqə döngələrini necə həll etmək olar:
zəif (weak) və ya sahibsiz (unowned) istinadlardan istifadə edin.
weak: Bu, əlaqəli obyektinnilola biləcəyi halda istifadə olunur. İstinad avtomatik olaraqnilolur, obyekt sərbəst buraxıldıqda. Bu, opsionaldır.unowned: Bu, əlaqəli obyektin eyni və ya daha uzun ömürlü olduğu halda istifadə olunur vənilola bilməz.
weak istifadə edilən düzəldilmiş nümunə:
Apartment sinifində tenant istinadını zəifə çevirək:
class Apartment {
let unit: String
weak var tenant: Person? // weak istifadə olunur
init(unit: String) {
self.unit = unit
print("Apartment \(unit) initialize olunur")
}
deinit {
print("Apartment \(unit) sərbəst buraxılır")
}
}
İndi, Person obyekti sərbəst buraxıldıqda, tenant istinadı Apartment-də avtomatik olaraq nil olur və döngə qırılır, beləliklə Apartment də sərbəst buraxıla bilər.
weak və unowned müqayisə cədvəli:
| Xüsusiyyət | weak |
unowned |
|---|---|---|
| İstinad tipi | Opsional | Opsional deyil |
nil ola bilər? |
Bəli, obyekt sərbəst buraxıldıqda | Xeyr |
| Nə zaman istifadə etmək? | Əgər obyekt nil ola bilərsə |
Əgər obyekt nil olmamalıdırsa |
| Performans | nil yoxlaması səbəbindən biraz yavaş |
Bir az daha sürətli |
Həmçinin, döngələr tutma, bağlamalarda da baş verə bilər.
Bağlamalar self və ya obyektin xüsusiyyətlərini tutduqda, güclü istinad yarada bilər. Əgər bu obyekt də güclü istinadı olan bağlamaya sahibdirsə, döngə yaranır.
Bağlamalarda döngə tutma problemini necə həll etmək olar:
Capture list istifadə edin.
class SomeClass {
var value = 0
func doSomethingDelayed() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in // weak self capture list
guard let self = self else { return } // `self`-in `nil` olub-olmamasını yoxlamaq
self.value += 1
print("Value indi \(self.value)")
}
}
}
Bu nümunədə [weak self] zəif istinad yaradır və döngə tutma problemini qarşısını alır.