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'ektnilbo'lishi mumkin bo'lgan holatlarda ishlatiladi. Murojaat avtomatik ravishdanilbo'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.nilbo'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.