Sobes.tech
Middle

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 obyektin nil ola biləcəyi halda istifadə olunur. İstinad avtomatik olaraq nil olur, 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ə nil ola 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.

weakunowned 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.