defer operatörü, diğer dillerdeki finally/using/RAII ile benzerlik göstererek, Swift'te kaynakların güvenli ve garantili bir şekilde serbest bırakılması veya bir scope'tan çıkış sırasında kodun yürütülmesi için tanıtılmıştır.
Çok aşamalı başlangıç, dosyalarla çalışma, fonksiyondan çıkış için çapraz senaryolar - kaynakların garantili olarak serbest bırakılmasını veya mantığın yürütülmesini (dosyayı kapatmak, mutex'i serbest bırakmak, nesneyi havuza iade etmek, geçici durumu sıfırlamak) gerektirir. defer öncesinde, her return'da bunu manuel olarak yapmak zorundaydık.
defer, mevcut scope'tan çıkıldığında kodun yürütülmesini garanti eder, çıkışın normal olup olmadığına veya bir hata ile gerçekleşip gerçekleşmediğine bakmaksızın. Birden fazla defer tanımlanabilir - bunlar tanımlandıkları sırayla tersine yürütülür.
Kaynağı serbest bırakma örneği:
func processFile(path: String) throws { let file = try openFile(path) defer { file.close() } // Hatalar olsa bile garantiyle çağrılacak // ... dosyayla çalışma ... }
Anahtar özellikler:
Defer değişkenleri referansla yakalayabilir mi ve bu closure'ların davranışını nasıl etkiler?
Evet, defer, çağrıldığı anda kullanılan tüm değişkenleri closure yakalama kurallarına göre yakalar (değer tipleri için kopya, referans tipleri için referans). Değişken bir dış değer değişkeninin yakalanması bir hata olacaktır - defer yürütüldüğünde değişmiş olabilir.
Döngüler ve fonksiyonlar içinde iç içe defer nasıl çalışır?
Bir defer döngü içinde tanımlanmışsa, her iterasyon tamamlandığında yürütülür:
for _ in 1...3 { defer { print("İterasyonun sonu") } print("İçeride") }
Şu çıktıyı verir:
İçeride
İterasyonun sonu
İçeride
İterasyonun sonu
İçeride
İterasyonun sonu
Defer hiç yürütülmeyebilir mi?
Defer'in kodun yürütülmesi, yalnızca scope gerçekten terk edildiğinde garanti edilir. Ancak süreç beklenmedik bir şekilde sona ererse (fatalError, çökme) veya çıkış çağrılırsa, defer çalışmaz. Ayrıca defer, nesne yöntemleri seviyesinde çalışmaz - yalnızca fonksiyon/blok scope'unda çalışır.
Dosya açıldıktan sonra ve onunla çalıştıktan sonra dönüş farklı return/throw'lar ile yapıldı, bir noktada dosyayı kapatmak unutuldu. Sonuç olarak açık dosya yöneticisi sisteme sızdı.
Artılar:
Eksiler:
Mutex'in güvenli bir şekilde kilidinin açılması, dosya tanımlayıcısının serbest bırakılması ve ilerleme bayrağının sıfırlanması için defer kullanımı:
func criticalSection() { lock() defer { unlock() } // ... çalışma ... }
Artılar:
Eksiler: