Middle
Povedzte nám o správe pamäte v iOS.
sobes.tech AI
Odpoveď od AI
iOS používa automatické spravovanie pamäti pomocou ARC (Automatic Reference Counting). ARC automaticky uvoľňuje objekty, keď na ne prestanú byť odkazy.
Hlavné koncepty:
- Silný odkaz: Zvyšuje počítadlo odkazov na objekt. Objekt nebude uvoľnený, kým na neho existujú silné odkazy.
- Slabý odkaz: nezvyšuje počítadlo odkazov. Používa sa na zabránenie cyklov silných odkazov. Odkazuje na objekt, ktorý môže byť uvoľnený. Ak je objekt uvoľnený, slabý odkaz sa stáva
nil. - Neporušený odkaz: Podobne ako slabý, nezvyšuje počítadlo odkazov. Používa sa, keď objekt, na ktorý odkazuje, má rovnaký alebo dlhší životný cyklus. Neporušený odkaz sa nestane
nilpri uvoľnení objektu. Pri pokuse o prístup k uvoľnenému objektu cez neporušený odkaz vznikne chyba behu.
Cyklus silných odkazov (Retain Cycles): Vznikajú, keď dva alebo viac objektov má navzájom silné odkazy, čo bráni ich uvoľneniu. Rieši sa to pomocou slabých alebo neporušených odkazov.
Príklad cyklu silných odkazov a jeho riešenie:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
print("\(name) sa inicializuje")
}
deinit {
print("\(name) sa deinitializuje")
}
}
class Apartment {
let unit: String
weak var tenant: Person? // Použitie slabého odkazu na zabránenie cyklu
init(unit: String) {
self.unit = unit
print("Apartmán \(unit) sa inicializuje")
}
deinit {
print("Apartmán \(unit) sa deinitializuje")
}
}
var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john // Tu vzniká cyklus
john = nil
unit4A = nil
// Metódy deinitializácie nie sú volané kvôli cyklu
Riešenie pomocou weak:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
print("\(name) sa inicializuje")
}
deinit {
print("\(name) sa deinitializuje")
}
}
class Apartment {
let unit: String
weak var tenant: Person? // Použitie slabého odkazu na zabránenie cyklu
init(unit: String) {
self.unit = unit
print("Apartmán \(unit) sa inicializuje")
}
deinit {
print("Apartmán \(unit) sa deinitializuje")
}
}
var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john
john = nil
unit4A = nil
// Obidva objekty sú správne deinitializované
Neporušené vs Slabé:
- Používaj
weak, keď odkaz môže byťnil(objekt môže byť uvoľnený prvý). - Používaj
unowned, keď odkaz vždy bude mať hodnotu (objekt, na ktorý odkazuje, má rovnaký alebo dlhší životný cyklus).
Closure a cykly odkazov:
Closure môžu zachytávať odkazy na objekty, čím vytvárajú cykly silných odkazov. Rieši sa to pomocou zoznamu zachytávania (capture list).
Príklad:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = {
[weak self] in // Zachytávanie `self` slabým odkazom
guard let self = self else {
return ""
}
var html = "<\(self.name)"
if let text = self.text {
html += ">\(text)</\(self.name)>"
} else {
html += " />"
}
return html
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name) sa deinitializuje")
}
}
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "ahoj, svet")
print(paragraph!.asHTML())
paragraph = nil
// Objekt je deinitializovaný
Ladenie problémov s pamäťou:
- Memory Graph Debugger: V Xcode umožňuje vizualizovať väzby medzi objektmi a odhaľovať cykly silných odkazov.
- Instruments (Allocations, Leaks): Nástroje na sledovanie alokácie a uvoľňovania pamäti, hľadanie únikov pamäti.