Sobes.tech
Middle

iOSda ushlab qolish sikllari (retain cycles) nima?

sobes.tech AI

AIdan javob

Retain tsikllar yuzaga keladi, agar ikki yoki undan ortiq ob'ektlar o'zaro kuchli murojaatga ega bo'lsa, bu "yopiq aylana" hosil qiladi. Natijada, har bir ob'ektning murojaat hisoblagichi nolga yetmaydi va ARC (Avtomatik murojaat hisoblash) tomonidan ozod qilinmaydi. Bu xotira oqiblariga olib keladi, chunki ob'ektlar foydalanilmay qolganidan keyin ham xotirada qoladi.

Misol:

class Person {
    let name: String
    var apartment: Apartment?

    init(name: String) {
        self.name = name
        print("\(name) inicializatsiya qilinmoqda")
    }

    deinit {
        print("\(name) deinitializatsiya qilinmoqda")
    }
}

class Apartment {
    let unit: String
    var tenant: Person?

    init(unit: String) {
        self.unit = unit
        print("Xonadon \(unit) inicializatsiya qilinmoqda")
    }

    deinit {
        print("Xonadon \(unit) deinitializatsiya qilinmoqda")
    }
}

Bu misolda, agar Person kuchli murojaatga ega bo'lsa Apartment ga, va Apartment kuchli murojaatga ega bo'lsa Person ga, bu ob'ektlar ozod qilinishga harakat qilganda, ular o'chirilmaydi, chunki murojaat hisoblagichlari nolga yetmaydi.

Retain tsikllarini qanday hal qilish mumkin:

weak yoki unowned murojaatlarni foydalaning.

  • weak: Bu, bog'langan ob'ekt nil bo'lishi mumkin bo'lgan holatlarda ishlatiladi. Murojaat avtomatik ravishda nil bo'ladi, ob'ekt ozod qilinadigan bo'lsa. Bu opsional.
  • unowned: Bu, bog'langan ob'ekt, murojaat qiluvchi ob'ekt bilan bir xil yoki undan uzoqroq davom etadigan holatda ishlatiladi. nil bo'lishi mumkin emas.

weak bilan to'g'irlash misoli:

tenant murojaatini Apartment klassida zaif qilib o'zgartiraylik:

class Apartment {
    let unit: String
    weak var tenant: Person? // weak ishlatilmoqda

    init(unit: String) {
        self.unit = unit
        print("Xonadon \(unit) inicializatsiya qilinmoqda")
    }

    deinit {
        print("Xonadon \(unit) deinitializatsiya qilinmoqda")
    }
}

Endi, Person ob'ekti ozod qilinadigan bo'lsa, tenant murojaati Apartmentda avtomatik ravishda nil bo'ladi, bu tsiklni buzadi va Apartment ham ozod qilinadi.

weak va unowned taqqoslash jadvali:

Xususiyat weak unowned
Murojaat turi Opsional Opsional emas
nil bo'lishi mumkinmi? Ha, ob'ekt ozod qilinayotganda Yo'q
Qachon ishlatiladi? Ob'ekt nil bo'lishi mumkin bo'lsa Ob'ekt nil bo'lmaydigan holatda
Ishlash tezligi nil tekshiruvi sababli biroz sekinroq Biroz tezroq

Shuningdek, retain tsikllar closurelarda ham yuzaga kelishi mumkin.

Bir closure, self yoki instansiya xususiyatlarini ushlasa, ob'ektga kuchli murojaat yaratishi mumkin. Agar bu ob'ekt ham kuchli murojaatga ega bo'lsa, (masalan, xususiyat-closure yoki delegat orqali), tsikl yuzaga keladi.

Closurelarda retain tsikllarini qanday hal qilish mumkin:

Capture list dan foydalaning.

class SomeClass {
    var value = 0

    func doSomethingDelayed() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in // weak self capture list bilan
            guard let self = self else { return } // `nil` tekshiruvi
            self.value += 1
            print("Qiymat hozir \(self.value)")
        }
    }
}

Bu misolda, [weak self] self ga zaif murojaat yaratadi va tsiklni oldini oladi.