ProgramlamaiOS geliştiricisi

Swift'te closure'larda value ve reference capture mekanizması nasıl çalışır? Capture sırasında hangi potansiyel tehlikeler ortaya çıkabilir ve bunlardan nasıl kaçınılır?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

Swift'te closure'lar (kapamalar) çevresel bağlamdan değerleri ve referansları "kapma" yeteneğine sahiptir. Eğer kaplanan değer bir değer tipi (struct, enum) ise, closure verileri kopyalar. Eğer bir referans (örneğin, sınıf) kaplanıyorsa, closure sınıfın örneğine bir referans saklar, bu da [weak self] veya [unowned self] kullanılmadığında retain cycle'a yol açabilir.

Capture mekanizması, asenkron görevler ve callback'ler uygulamayı sağlar, ancak yanlış kullanım bellek yönetimini zorlaştırır.

Örnek:

class MyClass { var value = 10 func doSomething() { let closure = { [weak self] in print(self?.value ?? "nil") } closure() } }

Bu örnekte, asenkron çalışma yürütüldüğü için güçlü referans döngüsünden kaçınmak amacıyla [weak self] kullanılmıştır.

Kandırmaca Soru.

Soru: "Her zaman [weak self] kullanımı, closure içinde self yakalandığında bellek sızıntısını garanti eder mi?"

Cevap: Hayır, eğer closure içinde güçlü bir referans oluşursa (örneğin, ara değişkenler üzerinden), [weak self] ile bile retain cycle elde edilebilir. Örneğin:

let closure = { [weak self] in let strongSelf = self strongSelf?.doSomething() }

Eğer closure'ı uzun ömürlü bir nesneye (örneğin, NotificationCenter) bağlarsanız, self için başka referanslar varsa retain cycle elde edebilirsiniz.

Konuyla ilgili bilgi eksikliğinden kaynaklanan gerçek hata örnekleri.


Hikaye 1

Bir iOS uygulama projesinde, bir ağ isteğine closure gönderirken [weak self] belirtmeyi unutan bir geliştirici oldu. Sonuç olarak, istek gerçekleştirilirken, kullanıcı ekranı kapasa bile view controller nesnesi serbest bırakılmadı. Bu, ağ işlemleri yoğun bir şekilde kullanıldığında bellek sızıntılarına yol açtı.


Hikaye 2

Zamanlayıcıya abonelik yapan karmaşık bir sistemde, weak kullanılmadan closure üzerinden abone olan bir nesne, bellekten ekran silindiğinde bile eylemlerine devam etti. Bu, artık hiyerarşide olmayan UI elemanlarının tekrar çağrılmasına yol açtı ve uygulamanın çökmesine neden oldu.


Hikaye 3

Veri önbellekleme uygulaması sırasında closure, uzun ömürlü önbellek nesnesinde self'in referansını [unowned self] anotasyonu olmadan yakaladı. Orijinal nesne yok edildikten sonra closure'dan self'e erişim, zaten serbest bırakılmış belleğe erişim gerektiriyordu ve uygulamanın çökmesine neden oldu.