Sobes.tech
Middle

Swift dilinde otomatik bellek yönetimi (ARC) mekanizması nasıl çalışır?

sobes.tech yapay zeka

AI'dan gelen yanıt

ARC (Otomatik Referans Sayımı) otomatik olarak sınıf örneklerine referansları izler ve yönetir. Bir örneğe güçlü referans kalmadığında belleği serbest bırakır. ARC yalnızca sınıf örnekleriyle çalışır, yapılar veya enumlar ile değil, çünkü bunlar değer tipleridir.

İki örnek arasındaki üç bağlantı türü:

  • Strong (Güçlü): Örneğin referans sayacını artıran bağlantı. Varsayılan olarak tüm referanslar güçlüdür.
  • Weak (Zayıf): Referans sayacını artırmayan bağlantı. Güçlü referans döngülerini önlemek için kullanılır. weak türündeki referanslar her zaman opsiyoneldir, çünkü örnek herhangi bir zamanda serbest bırakılabilir.
  • Unowned (Mülksüz): Referans sayacını artırmayan ve bağlı örneğin daha uzun süre var olacağı garanti edilen durumlarda kullanılır. Zorunlu değildir, ancak serbest bırakılmış örneğe erişmeye çalışmak çalışma zamanı hatasıyla sonuçlanır.

Güçlü referans döngüleri, iki veya daha fazla sınıf örneğinin birbirine güçlü referanslar tuttuğu durumlarda ortaya çıkar ve ARC'nin serbest bırakmasını engeller. Bu döngüleri önlemek için weak veya unowned referanslar kullanılır.

Güçlü referans döngüsüne örnek:

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

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

    deinit { // serbest bırakıldığında çağrılır
        print("\(name) deinitialization oluyor")
    }
}

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

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

    deinit { // serbest bırakıldığında çağrılır
        print("Apartment \(unit) deinitialization oluyor")
    }
}

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 // Hiçbir şey yazdırılmaz, çünkü güçlü referans döngüsü var

Döngüyü weak ile çözme:

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

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

    deinit {
        print("\(name) deinitialization oluyor")
    }
}

class Apartment {
    let unit: String
    weak var tenant: Person? // Zayıf referans

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

    deinit {
        print("Apartment \(unit) deinitialization oluyor")
    }
}

var john: Person?
var unit4A: Apartment?

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

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

john = nil // Person serbest bırakılır
unit4A = nil // Apartment serbest bırakılır

unowned ile çözüm:

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

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

    deinit {
        print("\(name) deinitialization oluyor")
    }
}

class CreditCard {
    let number: UInt64
    unowned let customer: Customer // Mülksüz referans

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

    deinit {
        print("Kart #\(number) deinitialization oluyor")
    }
}

var john: Customer?

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

john = nil // Customer ve CreditCard serbest bırakılır

ARC ve kapanışlar (closures): Closure'lar da güçlü döngüler oluşturabilir, sınıf örneklerini yakalayarak. Bunu önlemek için [weak self] veya [unowned self] kullanılır.

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

    lazy var asHTML: () -> String = { // lazy, self'yi kullanmadan önce kullanmak için
        [unowned self] in // Yakalama listesi
        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 oluyor")
    }
}

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

paragraph = nil // HTMLElement serbest bırakılır