Middle
Meséljen az iOS memória kezeléséről.
sobes.tech MI
Válasz az MI-től
Az iOS automatikus hivatkozásszámlálást (ARC) használ a memória kezelésére. Az ARC automatikusan felszabadítja az objektumokat, amint már nem hivatkoznak rájuk.
Fő fogalmak:
- Erős Hivatkozás: Növeli egy objektum hivatkozásszámát. Az objektum nem kerül felszabadításra, amíg vannak erős hivatkozások rá.
- Gyenge Hivatkozás: Nem növeli a hivatkozásszámot. Használják ciklusok elkerülésére. Egy objektumra mutat, amely felszabadulhat. Ha az objektum felszabadul, a gyenge hivatkozás
nillesz. - Unowned Hivatkozás: Hasonló a gyenge hivatkozáshoz, nem növeli a hivatkozásszámot. Akkor használják, amikor a hivatkozott objektum ugyanannyi vagy hosszabb élettartamú. Az unowned hivatkozás nem lesz
nila felszabaduláskor. Hozzáférés egy felszabadult objektumhoz futási időben hibát eredményez.
Erős ciklusok (Retain Cycles): Akkor fordulnak elő, amikor két vagy több objektum erős hivatkozásokat tart fenn egymásra, megakadályozva azok felszabadulását. Gyenge vagy unowned hivatkozásokkal oldhatók meg.
Példa erős ciklusra és megoldása:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
print("\(name) inicializálva")
}
deinit {
print("\(name) deinitializálva")
}
}
class Apartment {
let unit: String
weak var tenant: Person? // Gyenge hivatkozás a ciklus elkerülése érdekében
init(unit: String) {
self.unit = unit
print("Lakás \(unit) inicializálva")
}
deinit {
print("Lakás \(unit) deinitializálva")
}
}
var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john // Itt ciklus keletkezik
john = nil
unit4A = nil
// A deinitializálási metódusok nem hívódnak meg a ciklus miatt
Megoldás gyenge hivatkozással:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
print("\(name) inicializálva")
}
deinit {
print("\(name) deinitializálva")
}
}
class Apartment {
let unit: String
weak var tenant: Person? // Gyenge hivatkozás a ciklus elkerülése érdekében
init(unit: String) {
self.unit = unit
print("Lakás \(unit) inicializálva")
}
deinit {
print("Lakás \(unit) deinitializálva")
}
}
var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john
john = nil
unit4A = nil
// Mindkét objektum helyesen deinitializálódik
unowned vs weak:
- Használd a
weak-et, amikor a hivatkozásnil-vé válhat (az objektum elsőként szabadulhat fel). - Használd az
unowned-et, amikor a hivatkozás mindig értéket fog tartalmazni (az objektum, amelyre hivatkozik, ugyanannyi vagy hosszabb élettartamú).
Closures és ciklusok:
A closures képesek objektumokra hivatkozni, így ciklusokat hozhatnak létre. Ezt a capture list segítségével lehet megoldani.
Példa:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = {
[weak self] in // Gyenge capture
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) deinitializálva")
}
}
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
print(paragraph!.asHTML())
paragraph = nil
// Az objektum deinitializálódik
Memória hibák hibakeresése:
- Memory Graph Debugger: Az Xcode lehetővé teszi az objektumok közötti kapcsolatok vizualizálását és a ciklusok azonosítását.
- Instruments (Allocations, Leaks): Eszközök a memória allokációk és felszabadítások nyomon követésére, valamint a szivárgások felderítésére.