Sobes.tech
Middle

iOS'taki bellek yönetiminden bahsedin.

sobes.tech yapay zeka

AI'dan gelen yanıt

iOS, bellek yönetimi için otomatik referans sayımı (ARC) kullanır. ARC, referans kalmayınca nesneleri otomatik olarak serbest bırakır.

Ana kavramlar:

  • Güçlü Referans: Nesnenin referans sayacını artırır. Nesne, güçlü referanslar kalmadıkça serbest bırakılmaz.
  • Zayıf Referans: Referans sayacını artırmaz. Güçlü döngüleri önlemek için kullanılır. Serbest bırakılabilecek bir nesneye referans verir. Nesne serbest bırakılırsa, zayıf referans nil olur.
  • Sahipsiz Referans (unowned): Zayıf ile benzer, referans sayacını artırmaz. Referans verilen nesne yaşam döngüsü aynı veya daha uzun olan nesneler için kullanılır. Nesne serbest bırakıldığında, sahipsiz referans nil olmaz. Serbest bırakılan nesneye sahipsiz referansla erişim hatası verir.

Güçlü Referans Döngüleri (Retain Cycles): İki veya daha fazla nesne birbirine güçlü referanslar ile bağlandığında oluşur ve serbest bırakılmalarını engeller. Zayıf veya sahipsiz referanslar kullanılarak çözülür.

Örnek:

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

    init(name: String) {
        self.name = name
        print("\(name) başlatılıyor")
    }

    deinit {
        print("\(name) sonlandırılıyor")
    }
}

class Apartment {
    let unit: String
    var tenant: Person? // Güçlü referans, döngüye neden olur

    init(unit: String) {
        self.unit = unit
        print("Daire \(unit) başlatılıyor")
    }

    deinit {
        print("Daire \(unit) sonlandırılıyor")
    }
}

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

john!.apartment = unit4A
unit4A!.tenant = john // Döngü burada oluşur

john = nil
unit4A = nil
// Serbest bırakma metodları çağrılmaz çünkü döngü var

Çözüm weak kullanımıyla:

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

    init(name: String) {
        self.name = name
        print("\(name) başlatılıyor")
    }

    deinit {
        print("\(name) sonlandırılıyor")
    }
}

class Apartment {
    let unit: String
    weak var tenant: Person? // Döngüyü önlemek için weak referans kullan

    init(unit: String) {
        self.unit = unit
        print("Daire \(unit) başlatılıyor")
    }

    deinit {
        print("Daire \(unit) sonlandırılıyor")
    }
}

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

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

john = nil
unit4A = nil
// Her iki nesne de doğru şekilde sonlandırılır

Sahipsiz (unowned) vs Zayıf (weak):

  • weak kullanılır, referans nil olma ihtimali varsa (nesne önce serbest bırakılabilir).
  • unowned kullanılır, referans her zaman bir değer olacaksa (referans verilen nesne daha uzun veya eşit yaşam döngüsüne sahipse).

Kapanışlar (Closures) ve döngüler:

Kapanışlar, nesnelere referanslar yakalayabilir ve güçlü döngüler oluşturabilir. Bu, yakalama listesi (capture list) kullanılarak çözülür.

Örnek:

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

    lazy var asHTML: () -> String = {
        [weak self] in // self'yi zayıf yakala
        guard let self = self else {
            return ""
        }
        var html = "<\(self.name)"
        if let text = self.text {
            html += ">\(text)</\(self.name)>"
        } else {
            html += " />"
        }
        return html
    }

    init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
    }

    deinit {
        print("\(name) sonlandırılıyor")
    }
}

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

paragraph = nil
// Nesne sonlandırılır

Bellek sorunlarının hata ayıklaması:

  • Memory Graph Debugger: Xcode'da nesneler arasındaki bağlantıları görselleştirir ve döngüleri tespit eder.
  • Instruments (Allocations, Leaks): Bellek tahsisi ve serbest bırakmayı izler, sızıntıları tespit eder.