Middle
Реците нам о управљању меморијом у iOS.
sobes.tech АИ
Одговор од АИ
iOS koristi automatsko brojanje referenci (ARC) za upravljanje memorijom. ARC automatski oslobađa objekte čim na njih prestanu da se odnose reference.
Glavni koncepti:
- Jake Reference: Povećava brojač referenci objekta. Objekat neće biti oslobođen dok postoje jake reference na njega.
- Slabe Reference: Ne povećava brojač referenci. Koristi se za sprečavanje ciklusa jakih referenci. Referira na objekat koji može biti oslobođen. Ako je objekat oslobođen, slaba referenca postaje
nil. - Unowned Referenca: Slično slabo, ne povećava brojač referenci. Koristi se kada objekat na koji se referiše ima isti ili duži životni vek. Unowned referenca ne postaje
nilpri oslobađanju objekta. Pristup oslobođenom objektu putem unowned izaziva grešku u izvršenju.
Ciklus jakih referenci (Retain Cycles): Javljaju se kada dva ili više objekata imaju jake reference jedan na drugog, sprečavajući njihovo oslobađanje. Rešavaju se pomoću slabih ili unowned referenci.
Primer ciklusa i rešenje:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
print("\(name) se inicijalizuje")
}
deinit {
print("\(name) se deinitializuje")
}
}
class Apartment {
let unit: String
weak var tenant: Person? // Koristi se slab referenca za sprečavanje ciklusa
init(unit: String) {
self.unit = unit
print("Stan \(unit) se inicijalizuje")
}
deinit {
print("Stan \(unit) se deinitializuje")
}
}
var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john // Ovde nastaje ciklus
john = nil
unit4A = nil
// Metode deinit nisu pozvane zbog ciklusa
Rešenje pomoću slabog odnosa:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
print("\(name) se inicijalizuje")
}
deinit {
print("\(name) se deinitializuje")
}
}
class Apartment {
let unit: String
weak var tenant: Person? // Koristi se slab referenca za sprečavanje ciklusa
init(unit: String) {
self.unit = unit
print("Stan \(unit) se inicijalizuje")
}
deinit {
print("Stan \(unit) se deinitializuje")
}
}
var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john
john = nil
unit4A = nil
// Oba objekta se pravilno deinitializuju
unowned vs weak:
- Koristi
weakkada referenca može postatinil(objekat može biti prvi oslobođen). - Koristi
unownedkada referenca uvek ima vrednost (objekat na koji se odnosi ima isti ili duži životni vek).
Closures i ciklusi referenci:
Closures mogu uhvatiti reference na objekte, stvarajući cikluse jakih referenci. To se rešava pomoću capture liste.
Primer:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = {
[weak self] in // Slaba referenca na self
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) se deinitializuje")
}
}
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
print(paragraph!.asHTML())
paragraph = nil
// Objekat se deinitializuje
Dijagnostika problema sa memorijom:
- Memory Graph Debugger: U Xcode omogućava vizualizaciju veza između objekata i identifikaciju ciklusa jakih referenci.
- Instruments (Allocations, Leaks): Alati za praćenje dodeljivanja i oslobađanja memorije, kao i za pronalaženje curenja.