Swiftте автоматтык эс тутумду башкаруу (ARC) кантип иштейт?
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("Квартира \(unit) ишке киргизилди")
}
deinit {
print("Квартира \(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? // Weak reference колдонуу
init(unit: String) {
self.unit = unit
print("Квартира \(unit) ишке киргизилди")
}
deinit {
print("Квартира \(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 дезинциализацияланат
Тандоо слаб же бош шилтемелердин ортосунда, объекттердин ортосундагы мамилеге байланыштуу:
- Weak: Эгер бир объект башка объектке
nilболушу мүмкүн болсо, ал опционалдуу мааниде болот. - Unowned: Эгер бир объект дайыма башка объекттин ичинде болот жана ал өзгөрбөсө, анда ал опционал эмес болот.
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) жабык циклдин ичинде nil болбойт:
ARC Swiftте эс тутумду башкарууну автоматташтырып, оңой кылды, бирок шилтемелердин түрлөрүн түшүнүү керек, анткени ал эс тутумдун агып кетишин алдын алат.