Middle
Խոսեք մեզ iOS-ի հիշողության կառավարման մասին։
sobes.tech AI
Պատասխան AI-ից
iOS օգտագործում է ավտոմատ հիշողության կառավարում՝ ARC (Automatic Reference Counting) միջոցով: ARC ինքնաբերաբար ազատում է օբյեկտները, երբ նրանց վրա այլ հղումներ չկան:
Հիմնական հասկացությունները՝
- Strong Reference: Օբյեկտի հղման հաշվիչը բարձրացնում է: Օբյեկտը չի ազատվի, քանի դեռ կա ուժեղ հղում:
- Weak Reference: Չբարձրացնում է հղման հաշվիչը: Օգտագործվում է ուժեղ հղումների ցիկլերը կանխելու համար: Հղում է դեպի օբյեկտ, որը կարող է ազատվել: Եթե օբյեկտը ազատվի, weak հղումը դառնում է
nil: - Unowned Reference: Դիպուկ նման է weak-ին, բայց չի դառնում
nilօբյեկտի ազատման ժամանակ: Օգտագործվում է, երբ օբյեկտը միշտ առկա է կամ ունի նույն կամ երկարատև կյանք:
Ցիկլեր ուժեղ հղումների (Retain Cycles): առաջանում են, երբ երկու կամ ավելի օբյեկտներ ունեն միմյանց ուժեղ հղումներ, ինչը խոչընդոտում է նրանց ազատմանը:
Օրինակ՝
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
print("\(name) սկսում է աշխատել")
}
deinit {
print("\(name) ավարտում է")
}
}
class Apartment {
let unit: String
weak var tenant: Person? // Weak հղում՝ ցիկլը կանխելու համար
init(unit: String) {
self.unit = unit
print("Apartment \(unit) սկսում է աշխատել")
}
deinit {
print("Apartment \(unit) ավարտում է")
}
}
var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john // Այստեղ առաջանում է ցիկլ
john = nil
unit4A = nil
// Դե-ինիցիալիզացիայի մեթոդները չեն կանչվում ցիկլի պատճառով
Որպես լուծում՝ օգտագործել weak:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
print("\(name) սկսում է աշխատել")
}
deinit {
print("\(name) ավարտում է")
}
}
class Apartment {
let unit: String
weak var tenant: Person? // Weak հղում՝ ցիկլը կանխելու համար
init(unit: String) {
self.unit = unit
print("Apartment \(unit) սկսում է աշխատել")
}
deinit {
print("Apartment \(unit) ավարտում է")
}
}
var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john
john = nil
unit4A = nil
// Երկու օբյեկտներն էլ ճիշտ կերպով դե-ինիցիալիզացվում են
Unowned vs Weak:
- Օգտագործիր
weak, երբ հղումը կարող է դառնալnil(օբյեկտը կարող է առաջինը ազատվել) - Օգտագործիր
unowned, երբ հղումը միշտ կունենա արժեք (օբյեկտը, որի վրա հղում է, ունի նույն կամ երկարատև կյանք)
Closure-ներ և ցիկլեր հղումներ:
Closure-ները կարող են բռնել օբյեկտների հղումներ, ստեղծելով ուժեղ ցիկլեր: Սա լուծվում է capture list-ով:
Օրինակ՝
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = {
[weak self] in // բռնում ենք `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) ավարտում է")
}
}
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "բարև, աշխարհ")
print(paragraph!.asHTML())
paragraph = nil
// Օբյեկտը դե-ինիցիալիզացվում է
Հիշողության խնդիրների դե-բագինգ:
- Memory Graph Debugger: Xcode- ում թույլ է տալիս տեսնել օբյեկտների կապերը և հայտնաբերել ցիկլեր
- Instruments (Allocations, Leaks): Օգտագործվում է հիշողության բաշխումը և ազատումը մոնիտորինգի համար, նաև թափանցիկության որոնման համար։