.onDisappear, bir View arayüz hiyerarşisinden kaldırıldığında bir closure çalıştıran SwiftUI değiştiricisidir. Çağrı, ekran kapatıldığında, sekme değiştirildiğinde, modal pencere kapatıldığında veya bir öğe görünürlük dışına kaydırıldığında gerçekleşir. Apple Developer Documentation'a (2026) göre onDisappear, çökme senaryolarında veya uygulama sistem watchdog tarafından sonlandırıldığında çağrıyı garanti etmez. SwiftUI hakkında daha fazla bilgi için SwiftUI makalesine bakın.
Önemli Noktalar
.onDisappear, SwiftUI'de bir Void closure alan ve View hiyerarşiden kaldırıldığında bunu çalıştıran bir View değiştiricisidir. .onAppear ile birlikte bir ekranın tam yaşam döngüsünü oluşturur: görünme — çalışma — kaybolma. Apple, onDisappear'ı SwiftUI ile birlikte iOS 13'te UIKit'teki viewDidDisappear'ın benzeri olarak tanıttı.
Sözdizimsel olarak .onDisappear, onAppear ile aynıdır: herhangi bir View'i değiştirir ve SwiftUI oluşturucusunun view kaldırıldığında çağırdığı bir closure ekler. Geçiş animasyonunun tamamlanmasından sonra tetiklenen UIKit'teki viewDidDisappear'ın aksine, SwiftUI'de onDisappear animasyon bitmeden — View'in kaldırılmak üzere işaretlendiği anda çağrılabilir.
Temel sözdizimi onDisappear'ın onAppear kadar kısadır. Değiştirici ek parametre almaz — yalnızca ana iş parçacığında eşzamanlı olarak çalışan closure.
struct DetailView: View {
var body: some View {
Text("Detail Screen")
.onDisappear {
print("DetailView ekrandan kayboldu")
}
}
}
Çağrı mekanizması onDisappear'ın onAppear'ın tersidir: alt öğeler önce onDisappear alır, sonra üst öğe. Bu child-first kuralı, üst kaynakları serbest bırakılmadan önce alt kaynakların serbest bırakılmasını sağlar. Bir alt öğe üst verilere bağımlıysa, üst bağlamı olmadan doğru şekilde sonlanabilmelidir.
SwiftUI, View oluşturma grafiğinden kaldırıldığında onDisappear'ı çağırır. Tetikleyiciler şunları içerir: NavigationStack'ten pop, TabView değiştirme, modal kapatma (sheet/fullScreenCover) veya koşullu olarak oluşturulan View (if/switch). List ve ScrollView'da, bir hücre önceden yükleme arabelleğinin dışına kaydırıldığında onDisappear çağrılır.
Child-first sırası, bir VStack'te üç alt View varsa, onDisappear'ın önce her alt için ters sırada, sonra üst için çağrıldığı anlamına gelir. Bu, doğru temizlik için kritiktir: üst ViewModel paylaşılan kaynakları serbest bırakmadan önce alt zamanlayıcılar iptal edilir.
struct ParentView: View {
var body: some View {
VStack {
ChildView(id: "A")
ChildView(id: "B")
}
.onDisappear {
print("Parent onDisappear — son")
}
}
}
struct ChildView: View {
let id: String
var body: some View {
Text("Child \(id)")
.onDisappear {
print("Child \(id) onDisappear")
}
}
}
Konsol çıktısı: Child B onDisappear, Child A onDisappear, Parent onDisappear — son. onAppear'a kıyasla ters sıra, doğru temizleme zincirini garanti eder.
Çağrı senaryoları onDisappear'ın kapsayıcı türüne bağlıdır. NavigationStack'te onDisappear, pop-to-root, normal pop-back veya kaydırarak (interactivePopGestureRecognizer) ekran kapatmada tetiklenir. TabView'da sekme değiştirme, gizli sekme için onDisappear'ı ve gösterilen sekme için onAppear'ı çağırır — her iki değiştirici neredeyse aynı anda tetiklenir.
Sheet ve fullScreenCover'da onDisappear, programatik kapatmada (@Environment(\.dismiss) aracılığıyla) veya aşağı kaydırma hareketinde çağrılır. Önemli bir ayrıntı: bir sheet açıldıysa ancak kullanıcı uygulamayı değiştirdiyse, onDisappear fiili kapanışa kadar çağrılmaz.
| Senaryo | onDisappear çağrılır | Not |
|---|---|---|
| NavigationStack'te Pop | Evet | Animasyondan hemen sonra |
| TabView sekme değişimi | Evet | Mevcut sekme |
| Sheet kapatma | Evet | Animasyon tamamlanmadan önce |
| List'te kaydırma | Evet | Hücre ön yükleme bölgesinden çıktı |
| Uygulamayı küçültme | Hayır | Çağrı garantisi yok |
| Çökme/watchdog kill | Hayır | Çağrılmaz |
Ana kullanım durumları onDisappear'ın kaynak temizliği, durum kaydetme ve izlemedir. onAppear'ın aksine, onDisappear görevleri çıkışta çalıştırılır ve yinelenme kontrolü gerektirmez çünkü View bir kez kaybolur.
Durum kaydetme onDisappear'da, ekrandan ayrılırken verilerin kaydedilmesi gereken formlar için özellikle kullanışlıdır. Zamanlayıcılar ve Combine abonelikleri, ekrana dönerken sızıntıları önlemek için onDisappear'da iptal edilir.
struct FormView: View {
@State private var draftText = ""
@State private var timer: Timer?
var body: some View {
TextField("Enter text", text: $draftText)
.onAppear {
timer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true) { _ in
saveDraft()
}
}
.onDisappear {
timer?.invalidate()
timer = nil
saveDraft()
}
}
private func saveDraft() {
UserDefaults.standard.set(draftText, forKey: "draft")
}
}
Zamanlayıcı iptali onDisappear'da, ekran zaten kapatıldıktan sonra kod çalışmasını önler. İptal edilmezse, zamanlayıcı artık mevcut View'e ait olmayan @State'i güncellemeye çalışarak çalışma zamanı uyarısına neden olabilir.
Ekranda kalma süresi klasik bir izleme senaryosudur. onAppear'da zamanı kaydedin, onDisappear'da farkı hesaplayın ve oturum süresiyle birlikte bir analitik olayı gönderin.
struct TrackedView: View {
@State private var appearTime: Date?
var body: some View {
Text("Tracked Screen")
.onAppear {
appearTime = Date()
Analytics.shared.logEvent("screen_view", params: ["screen": "TrackedView"])
}
.onDisappear {
if let start = appearTime {
let duration = Date().timeIntervalSince(start)
Analytics.shared.logEvent("screen_close", params: [
"screen": "TrackedView",
"duration_ms": Int(duration * 1000)
])
}
}
}
}
Temel fark onDisappear ve onAppear arasındaki çağrı sırası ve yürütme garantileridir. onAppear, View hiyerarşiye eklendiğinde çağrılır ve yeniden oluşturmada tekrar çağrılabilir. onDisappear kaldırmada çağrılır ve yalnızca normal kapanışta tetiklenmesi garanti edilir, çökme senaryolarında değil.
WWDC 2024'e göre Apple, onDisappear'ı bir veri kayıt noktası değil, bir temizlik noktası olarak ele almayı önerir. Kritik veriler (ödemeler, kayıtlar) View kaybolduğu anda değil, gerçek zamanlı olarak kaydedilmelidir çünkü uygulama küçültüldüğünde onDisappear garanti edilmez.
| Özellik | .onAppear | .onDisappear |
|---|---|---|
| Çağrı anı | View hiyerarşiye eklendi | View hiyerarşiden kaldırıldı |
| Sıra | Parent-first | Child-first |
| Garanti | Yüksek | Çökmelerde yok |
| Ana görev | Başlatma | Temizlik |
| Tekrarlanan çağrı | View yeniden oluşturmada | Kaybolma başına bir kez |
Öneri: onDisappear'ı yalnızca kritik olmayan temizlik ve izleme için kullanın. Veri kalıcılığı için AppDelegate'te scenePhase veya applicationWillTerminate bildirimlerini kullanın.
Senaryo 1: YouTube benzeri oynatma. Video detay ekranında onDisappear, oynatma konumunu UserDefaults'a kaydeder. Yeniden açıldığında onAppear, UserDefaults'tan konumu geri yükleyerek sürekli bir izleme deneyimi sağlar.
Senaryo 2: Combine aboneliğini iptal etme. Bir ViewModel Combine yayıncıları kullanıyorsa, onDisappear cancellable?.cancel() ile aboneliği iptal eder. Bu, ekrandan ayrıldıktan sonra UI güncellemelerini önler; sayfalama içeren listeler ve arama sorguları için özellikle önemlidir.
Senaryo 3: WebSocket kapatma. Gerçek zamanlı bağlantıları olan uygulamalarda (mesajlaşma, kotasyon akışları) onDisappear, pil ve veri tasarrufu için WebSocket bağlantısını kapatır. Ekrana dönüşte onAppear'da yeniden bağlantı gerçekleşir.
WebSocket, ekrandan ayrılırken kapatılması gereken tipik bir kaynaktır. Aşağıdaki örnekte onDisappear soket bağlantısını keser ve onAppear yeniden bağlanır; bu, birden çok ekranlı uygulamalar için önemli veri tasarrufu sağlar.
struct ChatView: View {
@StateObject private var socket = WebSocketManager()
var body: some View {
ChatListView(messages: socket.messages)
.onAppear {
socket.connect()
}
.onDisappear {
socket.disconnect()
}
}
}
Önemli: TabView sekmeleri arasında geçiş yaparken, mevcut sekmelerin onDisappear'ı ve sonraki sekmelerin onAppear'ı neredeyse aynı anda tetiklenir. WebSocket için bu, gereksiz yük oluşturan bir bağlantı kesme-yeniden bağlanma döngüsüne neden olabilir. Çözüm, bir gecikme kullanmak veya sonraki ekranda sokete ihtiyaç olup olmadığını kontrol etmektir.
Sıkça Sorulan Sorular
Evet, .onDisappear uygulama çökmesi (crash, watchdog kill), ekranı kapatmadan uygulamayı küçültme veya uygulamanın arka planda sonlandırıldığı sistem senaryolarında çağrıyı garanti etmez. Kritik veriler için scenePhase veya applicationWillTerminate kullanın.
.onDisappear, View hiyerarşiden kaldırıldığında tetiklenir — belirli bir ekran için yerel bir geri çağrı. .scenePhase (@Environment(\.scenePhase) aracılığıyla) tüm uygulama durumu değiştiğinde tetiklenir: active, inactive, background. Ekran süresi izleme için onAppear+onDisappear ve küresel durum kalıcılığı için scenePhase kullanın.
Neden, hızlı sekme değiştirme veya aynı ekranın tekrarlanan push/pop'udur. SwiftUI yeni bir View örneği oluşturabilir, eskisini kaldırabilir, tekrar oluşturabilir — her seferinde onDisappear ve onAppear'ı çağırarak. .id(), .equatable() kullanıp kullanmadığınızı veya üst gövdede View'i yeniden oluşturup oluşturmadığınızı kontrol edin.
Evet, .onDisappear macOS'ta (10.15+) aynı davranışla tam olarak desteklenir: pencere kapatıldığında, split view paneli kaldırıldığında veya modal kapatıldığında çağrılır. macOS'ta onDisappear, pencere gizlendiğinde de çağrılır (yalnızca kapatıldığında değil), bu macOS uygulamaları için dikkate alınması önemlidir.
@State'te URLSessionTask'e bir referans kaydedin ve onDisappear'da task.cancel()'ı çağırın. Alternatif olarak, View kaybolduğunda async işlemi otomatik olarak iptal eden .task değiştiricisini kullanın. .task, URLSession dahil tüm async işlemler için tercih edilir.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun