Sobes.tech
Middle

Swift dilində avtomatik yaddaş idarəetmə mexanizmi (ARC) necə işləyir?

sobes.tech Süni İntellekt

AI-dan cavab

ARC (Avtomatik Referans Sayma) nümunələrə istinadları avtomatik izləyir və idarə edir. O, nümunənin istifadə olunmayan yaddaşını azad edir, əgər ona qarşı güclü istinadlar qalmayıbsa. ARC yalnız sinif nümunələri ilə işləyir, struktur və ya enumerasiya ilə yox, çünki onlar dəyər tipləridir.

Nümunələr arasında üç növ istinad:

  • Strong (Güclü): Nümunənin istinad sayğacını artıran istinad. Əsasən bütün istinadlar güclüdür.
  • Weak (Zəif): Sayğacı artırmayan istinad. Güclü istinad dövrlərini qarşısını almaq üçün istifadə olunur. weak tipli istinadlar həmişə opsionaldır, çünki nümunə hər zaman azad edilə bilər.
  • Unowned (Mülkiyyətsiz): Sayğacı artırmayan və nümunənin daha uzun müddət mövcud olacağına əmin olunduğu zaman istifadə olunan istinad. Zəruri deyil, lakin azad edilən nümunəyə giriş cəhdi icra zamanı xəta ilə nəticələnir.

Güclü istinad dövrləri, iki və ya daha çox sinif nümunəsinin bir-birinə güclü istinadlar saxlaması nəticəsində yaranır və ARC-nin onları azad etməsinə mane olur. Bu dövrləri həll etmək üçün weak və ya unowned istinadlar istifadə olunur.

Güclü istinad dövrünün nümunəsi:

class Person {
    let name: String
    var apartment: Apartment?

    init(name: String) {
        self.name = name
    }

    deinit { // azad edilərkən çağırılır
        print("\(name) azad edilir")
    }
}

class Apartment {
    let unit: String
    var tenant: Person?

    init(unit: String) {
        self.unit = unit
    }

    deinit { // azad edilərkən çağırılır
        print("Mənzil \(unit) azad edilir")
    }
}

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 // Heç bir şey çap edilmir, çünki güclü istinad dövrü mövcuddur

Güclü istinad dövrünü weak ilə həll etmək:

class Person {
    let name: String
    var apartment: Apartment?

    init(name: String) {
        self.name = name
    }

    deinit {
        print("\(name) azad edilir")
    }
}

class Apartment {
    let unit: String
    weak var tenant: Person? // Zəif istinad

    init(unit: String) {
        self.unit = unit
    }

    deinit {
        print("Mənzil \(unit) azad edilir")
    }
}

var john: Person?
var unit4A: Apartment?

john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")

john!.apartment = unit4A
unit4A!.tenant = john

john = nil // Person azad edilir
unit4A = nil // Mənzil azad edilir

Güclü istinad dövrünü unowned ilə həll etmək:

class Customer {
    let name: String
    var card: CreditCard?

    init(name: String) {
        self.name = name
    }

    deinit {
        print("\(name) azad edilir")
    }
}

class CreditCard {
    let number: UInt64
    unowned let customer: Customer // Mülkiyyətsiz istinad

    init(number: UInt64, customer: Customer) {
        self.number = number
        self.customer = customer
    }

    deinit {
        print("Karta #\(number) azad edilir")
    }
}

var john: Customer?

john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)

john = nil // Customer və CreditCard azad edilir

ARC və closure-lərdə: Closure-lər də sinif nümunələrinə güclü dövrlər yarada bilər, onları tutaraq. Bu dövrləri qarşısını almaq üçün [weak self] və ya [unowned self] istifadə olunur.

class HTMLElement {
    let name: String
    let text: String?

    lazy var asHTML: () -> String = { // lazy, self-dən əvvəl istifadə üçün
        [unowned self] in // Məlumat tutma siyahısı
        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) azad edilir")
    }
}

var paragraph: HTMLElement? = HTMLElement(name: "p", text: "salam, dünya")
print(paragraph!.asHTML())

paragraph = nil // HTMLElement azad edilir