Sobes.tech
Middle

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. weak turidagi 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