Mis on hoidmis- (retain) tsüklid iOS-is?
sobes.tech AI
Vastus AI-lt
Atkārtojuma cikli veidojas, kad divi vai vairāki objekti ir stipri saistīti viens ar otru, radot "aizvērto loku". Rezultātā katra objekta atsauces skaitītājs nekad nesasniedz nulli, un tas nevar tikt atbrīvots ar ARC (Automātisko atsauču skaitīšanu). Tas noved pie atmiņas noplūdēm, jo objekti paliek atmiņā pat tad, kad tie vairs netiek izmantoti.
Piemērs:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
print("\(name) tiek inicializēts")
}
deinit {
print("\(name) tiek de-inicializēts")
}
}
class Apartment {
let unit: String
var tenant: Person?
init(unit: String) {
self.unit = unit
print("Apartment \(unit) tiek inicializēts")
}
deinit {
print("Apartment \(unit) tiek de-inicializēts")
}
}
Šajā piemērā, ja Person ir stipra saite uz Apartment, un Apartment ir stipra saite uz Person, tad, mēģinot atbrīvot šos objektus, tie netiks izņemti, jo to atsauces skaitītāji nekad nesasniedz nulli.
Kā novērst cikliskās saites:
Izmantojiet vagas (weak) vai neapzinātas (unowned) saites.
weak: Izmanto, kad ir iespējams, ka saistītais objekts kļūsnildzīves laikā. Atsauce automātiski kļūstnil, kad objekts, uz kuru tā norāda, tiek atbrīvots. Ir opcionala.unowned: Izmanto, kad ir zināms, ka saistītais objekts ir tāds pats vai ilgāks dzīves cikls nekā objekts, kam ir atsauce uz to. Navnil.
Labots piemērs ar weak:
Mainīsim tenant saiti Apartment klasē uz vājo:
class Apartment {
let unit: String
weak var tenant: Person? // Izmanto `weak`
init(unit: String) {
self.unit = unit
print("Apartment \(unit) tiek inicializēts")
}
deinit {
print("Apartment \(unit) tiek de-inicializēts")
}
}
Dabar, kad Person objekts tiek atbrīvots, saite tenant Apartment automātiski kļūst nil, pārtraucot ciklu un ļaujot Apartment arī tikt atbrīvotam.
Salīdzināšanas tabula weak un unowned:
| Raksturlielums | weak |
unowned |
|---|---|---|
| Saite tips | Opcionala | Opcionala nav |
Var būt nil? |
Jā, kad objekts tiek atbrīvots | Nē |
| Kada lietot | Kad objekts var kļūt nil |
Kad objekts nevar būt nil |
| Veiktspēja | Nedaudz lēnāk dēļ nil pārbaudes |
Nedaudz ātrāk |
Cikliskās saites var rasties arī ar slēdzieniem (closures).
Kad slēdzis iekļauj instance īpašības vai self, tas var radīt stipru saiti uz objektu. Ja šis objekts arī stipri saistīts ar slēdzi (piemēram, caur īpašību vai deleģentu), veidojas cikls.
Kā novērst cikliskās saites ar slēdzieniem:
Izmantojiet uzturēšanas sarakstu (capture list).
class SomeClass {
var value = 0
func doSomethingDelayed() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in // uzturēšanas saraksts ar weak self
guard let self = self else { return } // `self` pārbaude
self.value += 1
print("Value is now \(self.value)")
}
}
}
Šajā piemērā [weak self] izveido vājo saiti uz self slēdziena iekšpusē, novēršot ciklisko saiti.