Konu tarihçesi:
Escape analizi, derleyici optimizasyonu ve bellek yönetimi terimidir. Swift'te closure'ların ve ARC'nin aktif kullanımı nedeniyle önemlidir. Escape ve non-escaping closure'ların kavramlarıyla ilgilidir, bu da closure'ların işlevin kapsamının ötesine geçip geçemeyeceğini belirler.
Sorun:
Closure türünün yanlış belirlenmesi, bellek yönetimi hatalarına, sızıntılara, beklenmedik değişken yakalamalarına ve performans düşüşüne neden olur. Closure'ın ne zaman "kaçtığını" (escapes) ve ne zaman kaçmadığını net bir şekilde anlamak ve bunları doğru şekilde etiketlemek gerekir.
Çözüm:
Swift, escaping closure'ı @escaping özniteliği ile açıkça etiketlemenizi gerektirir. Non-escaping closure'lar yalnızca işlevin içinde yakalanabilir, bunlar otomatik olarak daha verimli bellek yönetimine sahiptir ve yakalanan değişkenleri daha güvenli bir şekilde kullanabilirler.
Farkın örneği:
// non-escaping closure (daha hızlı, çağrılmadan sonra saklanmaz) func performSync(block: () -> Void) { block() } // escaping closure (saklanabilir ve daha sonra çalıştırılabilir) var storedCompletion: (() -> Void)? func performAsync(block: @escaping () -> Void) { storedCompletion = block }
Anahtar özellikler:
Non-escaping olarak tanımlanan bir closure'ı, işlevin kaynak kodunda değişiklik yapmadan escaping olarak değiştirmek mümkün mü?
Hayır. @escaping özniteliği işlevin imzasında açıkça belirtilmelidir. Eğer bir closure işlevin içinde sınırlarını aşarsa — yalnızca escaping closure gereklidir, aksi takdirde derleyici hata verecektir.
Escaping closure içine self'i weak/unowned yakalama olmadan geçirmek güvenli midir?
Hayır. Escaping closure, self'i güçlü bir referansla yakalarsa potansiyel olarak bir retain cycle oluşturabilir. Yakalamayı açıkça yönetmek gerekir:
someAsync { [weak self] in self?.doSomething() }
Her zaman escape closure küreseldir (program sonuna kadar hafızada saklanır mı)?
Hayır. Hayat döngüsü depolama alanına bağlıdır. Eğer closure yalnızca geçici olarak saklanıyorsa veya özellik sıfırlanıyorsa, o özellik sahibi kaybettiğinde serbest bırakılacaktır. Sadece küresel nesnelere referans taşıyan veya bunları küresel değişkenlerde saklayan closure'lar küresel hale gelir.
Sınıfın yönteminin içinde @escaping olmadan closure saklanmış (derleyici hatası), daha sonra düzeltmişler, retain cycle korumasını unutarak — uygulamada bellek sızıntısı.
Artılar:
Eksiler:
Geliştirici her zaman hangi durumlarda escaping closure gerektiğini kontrol eder, self'i weak/unowned olarak yakalar, sızıntılardan kurtulur, bellek ile güvenli bir şekilde çalışır.
Artılar:
Eksiler: