ProgramlamaOrta/Senior iOS Geliştirici

Swift'te defer operatörünün özü nedir ve temel kullanım senaryoları, closure'lar ve kaynak yönetimi ile ilgili çalışma özellikleri nelerdir?

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

Cevap.

Sorunun Geçmişi

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.

Problem

Ç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.

Çözüm

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:

  • Herhangi bir scope'tan çıkışta (return, throw, break) yürütülür,
  • Birden fazla defer art arda tanımlanabilir - ters sırayla yürütülür,
  • Kaynak yönetimi, hata işlemleri, kilitleme/açma, geçici durumları sıfırlamak için çok faydalıdır.

Tuzak Sorular.

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.

Yaygın Hatalar ve Antipatternler

  • Asenkron işlemler için defer kullanmak (son defer serbest bırakma yapar, ancak asenkron kod henüz tamamlanmamıştır),
  • Dıştaki değişkenlerin gizlice yakalanması (çoklu iş parçacığında yarış durumu),
  • Birçok defer ardışık olarak tanımlamak - okunabilirlik ve hata ayıklama kaybolur.

Hayattan Bir Örnek

Olumsuz Durum

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:

  • Basit doğrusal mantık

Eksiler:

  • Her çıkışta kaynağı serbest bırakmayı unutmamak kolaydır
  • Bellek sızıntısı/kaynak sızıntısı

Olumlu Durum

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:

  • Kaynağın yüksek güvenliği
  • Hata sayısının azalması

Eksiler:

  • Çok sayıda defer olduğunda ek scope iç içeliği