Sobes.tech
Middle

Capture List'te her zaman weak veya unowned kullanmak gerekiyor mu?

sobes.tech yapay zeka

AI'dan gelen yanıt

Hayır, her zaman değil.

Retain cycle'ları önlemek için Capture List'te weak veya unowned kullanıyoruz.

Retain cycle, iki veya daha fazla nesne birbirine güçlü referanslar verdiğinde oluşur ve bu da belleğin serbest bırakılmasını engeller.

weak veya unowned kullanılması gereken durumlar, bir kapanışın güçlü şekilde self'ye (veya başka bir sınıf/aktor değişkenine) referans verdiği ve self'in (veya başka bir nesnenin) bu kapanışa güçlü referans verdiği durumdur.

Gerekli olabilecek durumlara örnekler:

  • Asenkron işlemler (ağ istekleri, veri işleme)
  • Observer deseni
  • Animasyon blokları
  • Dispatch kuyrukları

Eğer kapanış self'i (veya başka bir sınıf/aktor değişkenini) yakalamıyorsa veya yapısal tipler/enumerasyonlar yakalıyorsa, weak veya unowned kullanımı gerekmez.

weak ve unowned arasındaki farklar:

Tip Açıklama Ne zaman kullanılır
weak Zayıf (opsiyonel) referans. nil olabilir. Kapanışın yaşam döngüsü, yakalanan nesnenin yaşam döngüsünden kısa veya ona eşitse ve nesne kapanıştan önce nil olabiliyorsa.
unowned Sahipsiz (opsiyonel olmayan) referans. nil olamaz. Kapanışın yaşam döngüsü, yakalanan nesnenin yaşam döngüsünden kısa veya ona eşitse ve nesnenin kapanıştan önce var olacağı garanti ediliyorsa. Nesne kapanıştan önce serbest bırakılırsa, çökme olur (unowned referansı ile deallocated örneğe).

weak kullanımı örneği:

class MyClass {
    var name: String = "Test"

    func performAsyncOperation() {
        // Kapanış `self`'i yakalar.
        // MyClass, asenkron işlemin bitiminden önce serbest bırakılabilir.
        DispatchQueue.global().async { [weak self] in
            guard let self = self else {
                // `self` serbest bırakıldı, çıkış yap
                return
            }
            print("İşlem tamamlandı: \(self.name)")
        }
    }

    deinit {
        print("MyClass serbest bırakıldı")
    }
}

unowned kullanımı örneği:

class ViewController {
    var dismissButton: UIButton!

    func setupButton() {
        dismissButton.addTarget(self, action: #selector(dismiss), for: .touchUpInside)

        // Kapanış `self`'i yakalar.
        // `self` (ViewController) daha uzun süre yaşar veya en az onun kadar yaşar varsayılır.
        // Bu durumda, hedef-aksiyon bir kapanış değildir, ama `unowned` kavramını güçlü referans döngülerinde gösterir.
        // Eğer bu *bir* kapanış olsaydı, örneğin UIControl.Event işleyicisinde,
        // ve ViewController, tıklama sırasında mevcutsa:
        // dismissButton.addAction(UIAction { [unowned self] _ in
        //     self.dismiss(animated: true, completion: nil)
        // }, for: .touchUpInside)
    }

    @objc func dismiss() {
        // Görünüm denetleyicisini kapat
    }
}

Kapanış retain cycle oluşturmazsa, weak veya unowned kullanımı gerekmez ve hatta gereksiz kontroller oluşturabilir (weak durumunda) veya potansiyel çökme riskleri oluşturabilir (unowned durumunda).

Örneğin, self veya başka bir nesneyi yakalamayan ve kapanışın güçlü referansını alan bir kapanış:

func fetchData(completion: @escaping (Data) -> Void) {
    URLSession.shared.dataTask(with: URL(string: "...")!) { data, response, error in
        guard let data = data else { return }
        // Burada `self` veya diğer nesnelerin yakalanması yoktur, bu da retain cycle'ı tetiklemez.
        completion(data)
    }.resume()
}

Bu durumda, [weak self] veya [unowned self] kullanımı gerekmez.