Чӣ гуна кор мекунад идораи худкории хотира (ARC) дар Swift?
sobes.tech AI
Ҷавоб аз AI
ARC (Автоматиии ҳисоб кардани истинодҳо) дар Swift пайгирӣ ва идоракунии истифодаи хотираи барномаҳои шумост. Он ба таври автоматӣ блокҳои хотираро, ки аз ҷониби намунаҳои синфҳо истифода мешаванд, озод мекунад, вақте ки онҳо дигар лозим нестанд, ки ин ба пешгирии фиребҳои хотира кӯмак мекунад.
Ҳангоми эҷоди намунаи нав аз синф, ARC блоки хотираро барои нигоҳ доштани маълумот дар бораи он намуна тақсим мекунад. Вақте ки намуна дигар лозим нест, ARC ин хотираро озод мекунад, то барои дигар мақсадҳо истифода шавад.
ARC бо ҳисоб кардани шумораи истинодҳои қавӣ (strong references) ба ҳар як намунаи синф кор мекунад. Истиноди қавӣ истинодест, ки намунаи синфро дар хотира нигоҳ медорад. Вақте ки шумораи истинодҳои қавӣ ба намуна ба сифр мерасад, ARC хотираро озод мекунад.
Дар Swift се намуди истинодҳо мавҷуданд, ки ба ARC таъсир мерасонанд:
- Истинодҳои қавӣ (Strong References): шумораи истинодҳоро ба намуна зиёд мекунанд.
- Истинодҳои суст (Weak References): шумораи истинодҳоро зиёд намекунанд. Онҳоро барои пешгирии циклҳои истинодҳои қавӣ истифода мебаранд, вақте ки ду намунаи синф истинодҳои қавиро ба ҳам нигоҳ медоранд. Истиноди суст автоматӣ ба
nilтабдил меёбад вақте ки объекте, ки ба он ишора мекунад, деинициализатсия мешавад. - Истинодҳои беқарор (Unowned References): инчунин шумораи истинодҳоро зиёд намекунанд. Онҳоро вақте истифода мебаранд, ки шумо боварӣ доред, ки объекте, ки ба он ишора мекунад, ҳамеша ҳузур дорад, то вақте ки ҳозира аст. Онҳо опсионалӣ нестанд (
nil). кӯшиши дастрасӣ ба объекте, ки деинициализатсия шудааст, бо истиноди беқарор хатогии иҷроиро ба вуҷуд меорад.
Масалан, цикли истинодҳои қавӣ:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
print("\(name) ҳангоми оғозёбӣ")
}
deinit {
print("\(name) ҳангоми деинициализатсия")
}
}
class Apartment {
let unit: String
var tenant: Person?
init(unit: String) {
self.unit = unit
print("Apartment \(unit) ҳангоми оғозёбӣ")
}
deinit {
print("Apartment \(unit) ҳангоми деинициализатсия")
}
}
var john: Person?
var unit4A: Apartment?
john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john
john = nil // Person деинициализатсия намешавад
unit4A = nil // Apartment деинициализатсия намешавад
Барои ҳалли ин масъала, истифодаи истинодҳои суст ё беқарорро истифода баред. Дар ин ҳолат, tenant дар Apartment бояд истиноди суст бошад:
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? // Истифодаи истиноди суст
init(unit: String) {
self.unit = unit
print("Apartment \(unit) ҳангоми оғозёбӣ")
}
deinit {
print("Apartment \(unit) ҳангоми деинициализатсия")
}
}
var john: Person?
var unit4A: Apartment?
john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")
john?.apartment = unit4A
unit4A?.tenant = john
john = nil // Person деинициализатсия мешавад
unit4A = nil // Apartment деинициализатсия мешавад
Интихоб байни истиноди суст ва беқарор вобаста ба муносибати байни объектҳо:
- Суст: Агар яке аз объектҳо метавонад
nilшавад пеш аз он ки дигаре деинициализатсия шавад (қимати опционалӣ). - Беқарор: Агар яке аз объектҳо ҳамеша вуҷуд дошта бошад, то вақте ки дигаре вуҷуд дорад (қимати ғайриопционалӣ).
ARC инчунин хотираро, ки аз ҷониби занҷирҳо (closures) истифода мешавад, идора мекунад, ки намунаҳои синфҳоро дар бар мегирад. Циклҳои истинодҳои қавӣ метавонанд дар вақте ки занҷир намунаи синфро захира мекунад ва он намуна ҳамчунин истиноди қавӣ ба занҷир дорад, ба вуҷуд оянд. Барои пешгирӣ аз ин, рӯйхатҳои захира (capture lists) дар занҷирҳо истифода мешаванд.
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = {
// Бе рӯйхати захира, мумкин аст цикл қавӣ
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name)>"
}
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name) ҳангоми деинициализатсия")
}
}
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
print(paragraph!.asHTML())
paragraph = nil // HTMLElement ҳангоми деинициализатсия намешавад
Ҳалли бо истифода аз рӯйхати захира [weak self]:
class AnHTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = { [weak self] in // Истифодаи weak self
guard let self = self else { return "" } // Санҷиши мавҷудияти self
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name)>"
}
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name) ҳангоми деинициализатсия")
}
}
var paragraph: AnHTMLElement? = AnHTMLElement(name: "p", text: "hello, world")
print(paragraph!.asHTML())
paragraph = nil // AnHTMLElement деинициализатсия мешавад
Истифодаи [unowned self] имконпазир аст, агар шумо боварӣ дошта бошед, ки намунаи синф (self) пеш аз иҷрои занҷир нолӣ намешавад.
ARC ба таври назаррас идоракунии хотираро дар Swift содда мекунад, дар муқоиса бо идоракунии дастӣ, аммо талаб мекунад, ки намудҳои истинодҳоро фаҳмед, то аз фиребҳои хотира пешгирӣ кунед.