Escaping closure — bir closure'ın çağıran fonksiyonun kapsamından "çıktığı" durum (örneğin, asenkron yürütme için saklanır).
Swift'te fonksiyonlar varsayılan olarak non-escaping closure alır: closure, fonksiyon çağrısı içerisinde yürütülür.
Escaping belirtmek için @escaping anahtar kelimesi kullanılır:
func asyncTask(completion: @escaping () -> Void) { DispatchQueue.main.async { completion() } }
Ana farklar:
[weak self] veya [unowned self] belirtilmesi gerekir.DispatchQueue.async fonksiyonuna parametre olarak geçen closure’lar için her zaman @escaping yazmak gerekir mi?
— Evet. Çünkü DispatchQueue.async closure'ı yürütme anına kadar sakladığı için, closure escaping olur.
Örnek:
func foo(action: () -> Void) { DispatchQueue.main.async { action() // Derlenmeyecek: closure escaping olmalı. } } // Gerekli: func bar(action: @escaping () -> Void) { ... }
Hikaye
Kontrolör, escaping closure içinde self'e güçlü bir referans oluşturdu (örneğin, ağ isteği). Kontrolör ekranın dışına çıkar çıkmaz serbest bırakılmadı — güçlü bir retain cycle. Çözüm: [weak self] veya [unowned self] kullanmak.
Hikaye
Fonksiyon closure'ı DispatchQueue.async'e iletti, ancak onu escaping olarak işaretlemedi. Proje derlenmedi, hataları bulmak zor oldu çünkü fonksiyonlar iç içe geçmişti.
Hikaye
Closure içinde, closure'ın çağrıldığı anda zaten de-initialized olan bir nesneye erişildi ( [unowned self] kullanıldı). Sonuç: runtime çökmesi. Çözüm: [weak self] kullanmak ve nil kontrolü yapmak.