Swift tilida avtomatik xotira boshqarish mexanizmi (ARC) qanday ishlaydi?
sobes.tech AI
AIdan javob
ARC (Avtomatik Referanslar hisoblash) sinflar instanslariga bo'lgan murojaatlarni avtomatik ravishda kuzatadi va boshqaradi. U hech qanday kuchli murojaatlar bo'lmaganda, instansiya tomonidan egallanadigan xotirani bo'shatadi. ARC faqat sinf instansiyalari bilan ishlaydi, strukturalar yoki enumeratsiyalar bilan emas, chunki ular qiymat turlaridir.
Ikki yoki undan ortiq instansiyalar o'rtasidagi uch turdagi bog'lanishlar:
- Strong (Kuchli): Instansiyaga murojaat sonini oshiradigan bog'lanish. Standart holatda, barcha murojaatlar kuchli.
- Weak (Zaif): Murojaat sonini oshirmaydigan bog'lanish. Kuchli sikllarni oldini olish uchun ishlatiladi.
weakturidagi murojaatlar har doim ixtiyoriy, chunki instansiya har qanday vaqtda bo'shatilishi mumkin. - Unowned (Egasi bo'lmagan): Murojaat sonini oshirmaydigan va bog'langan instansiya uzoqroq mavjud bo'lishini kafolatlaganda ishlatiladigan bog'lanish. Majburiy emas, ammo bo'shatilgan instansiyaga kirishga harakat qilish ish vaqtida xato keltirib chiqaradi.
Kuchli murojaat sikllari, ikki yoki undan ortiq sinf instansiyalari o'zaro kuchli murojaatlarni saqlaganida yuzaga keladi va ARC ularni bo'shatmaydi. Bu sikllarni hal qilish uchun weak yoki unowned murojaatlar ishlatiladi.
Kuchli murojaat sikli misoli:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
}
deinit { // bo'shatish vaqtida chaqiriladi
print("\(name) deinitialization bo'lyapti")
}
}
class Apartment {
let unit: String
var tenant: Person?
init(unit: String) {
self.unit = unit
}
deinit { // bo'shatish vaqtida chaqiriladi
print("Apartment \(unit) deinitialization bo'lyapti")
}
}
var john: Person?
var unit4A: Apartment?
john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john
john = nil
unit4A = nil // Hech narsa chop etilmaydi, chunki kuchli sikl mavjud
Siklni weak bilan hal qilish:
class Person {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
}
deinit {
print("\(name) deinitialization bo'lyapti")
}
}
class Apartment {
let unit: String
weak var tenant: Person? // Zaif murojaat
init(unit: String) {
self.unit = unit
}
deinit {
print("Apartment \(unit) deinitialization bo'lyapti")
}
}
var john: Person?
var unit4A: Apartment?
john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john
john = nil // Person bo'shatiladi
unit4A = nil // Apartment bo'shatiladi
unowned bilan hal qilish:
class Customer {
let name: String
var card: CreditCard?
init(name: String) {
self.name = name
}
deinit {
print("\(name) deinitialization bo'lyapti")
}
}
class CreditCard {
let number: UInt64
unowned let customer: Customer // Egasi bo'lmagan murojaat
init(number: UInt64, customer: Customer) {
self.number = number
self.customer = customer
}
deinit {
print("Karta #\(number) deinitialization bo'lyapti")
}
}
var john: Customer?
john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
john = nil // Customer va CreditCard bo'shatiladi
ARC va yopishlar (closures): Yopishlar ham kuchli sikllar yaratishi mumkin, sinf instansiyalarini ushlab qolib. Buning oldini olish uchun [weak self] yoki [unowned self] ishlatiladi.
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = { // lazy, self'dan foydalanish uchun
[unowned self] in // "unowned self" bilan ushlab qolish
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) deinitialization bo'lyapti")
}
}
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "salom, dunyo")
print(paragraph!.asHTML())
paragraph = nil // HTMLElement bo'shatiladi