.onDisappear ایک SwiftUI موڈیفائر ہے جو انٹرفیس کے درجہ بندی سے View ہٹائے جانے پر کلوزر کو انجام دیتا ہے۔ کال اسکرین بند کرنے، ٹیب تبدیل کرنے، موڈل ونڈو کو مسترد کرنے یا عنصر کے دید سے باہر اسکرول ہونے پر ہوتی ہے۔ Apple Developer Documentation (2026) کے مطابق، onDisappear کریش منظرناموں یا سسٹم واچ ڈاگ کے ذریعے ایپ کے ختم ہونے پر کال کی ضمانت نہیں دیتا۔ SwiftUI کے بارے میں مزید جاننے کے لیے SwiftUI مضمون دیکھیں۔
اہم نکات
.onDisappear SwiftUI میں ایک View موڈیفائر ہے جو Void کلوزر لیتا ہے اور View کو درجہ بندی سے ہٹائے جانے پر اسے انجام دیتا ہے۔ .onAppear کے ساتھ یہ اسکرین کا مکمل لائف سائیکل تشکیل دیتا ہے: ظاہر ہونا — کام — غائب ہونا۔ Apple نے onDisappear کو SwiftUI کے ساتھ iOS 13 میں UIKit کے viewDidDisappear کے مشابہ کے طور پر متعارف کرایا۔
نحوی طور پر، .onDisappear onAppear جیسا ہے: یہ کسی بھی View میں ترمیم کرتا ہے اور ایک کلوزر منسلک کرتا ہے جسے SwiftUI رینڈرر View ہٹائے جانے پر کال کرتا ہے۔ UIKit کے برعکس، جہاں viewDidDisappear صرف منتقلی اینیمیشن مکمل ہونے کے بعد متحرک ہوتا ہے، SwiftUI میں onDisappear اینیمیشن ختم ہونے سے پہلے — View کے ہٹانے کے لیے نشان زد ہونے کے لمحے کال ہو سکتا ہے۔
بنیادی نحو onDisappear کا onAppear جتنا ہی مختصر ہے۔ موڈیفائر اضافی پیرامیٹرز نہیں لیتا — صرف کلوزر، جو مرکزی تھریڈ پر ہم آہنگی سے انجام پاتا ہے۔
struct DetailView: View {
var body: some View {
Text("Detail Screen")
.onDisappear {
print("DetailView اسکرین سے غائب ہو گیا")
}
}
}
کال میکانزم onDisappear کا onAppear کے برعکس ہے: چائلڈ عناصر پہلے onDisappear حاصل کرتے ہیں، پھر پیرنٹ۔ یہ child-first اصول اس بات کو یقینی بناتا ہے کہ پیرنٹ کے وسائل جاری ہونے سے پہلے چائلڈ وسائل جاری ہو جائیں۔ اگر کوئی چائلڈ عنصر پیرنٹ ڈیٹا پر منحصر ہے، تو اسے پیرنٹ سیاق و سباق کے بغیر صحیح طریقے سے ختم ہونے کے قابل ہونا چاہیے۔
SwiftUI onDisappear کو اس وقت کال کرتا ہے جب View رینڈر گراف سے ہٹا دیا جاتا ہے۔ محرکات میں شامل ہیں: NavigationStack سے pop، TabView تبدیل کرنا، موڈل مسترد کرنا (sheet/fullScreenCover)، یا مشروط طور پر پیش کردہ View (if/switch)۔ List اور ScrollView میں، onDisappear اس وقت کال ہوتا ہے جب سیل پری فیچ بفر سے باہر اسکرول ہوتی ہے۔
Child-first ترتیب کا مطلب ہے کہ اگر VStack میں تین چائلڈ View ہیں، تو onDisappear پہلے ہر چائلڈ کے لیے الٹی ترتیب میں کال ہوتا ہے، پھر پیرنٹ کے لیے۔ یہ مناسب صفائی کے لیے اہم ہے: پیرنٹ ViewModel کے مشترکہ وسائل جاری کرنے سے پہلے چائلڈ ٹائمر منسوخ ہو جاتے ہیں۔
struct ParentView: View {
var body: some View {
VStack {
ChildView(id: "A")
ChildView(id: "B")
}
.onDisappear {
print("Parent onDisappear — آخر میں")
}
}
}
struct ChildView: View {
let id: String
var body: some View {
Text("Child \(id)")
.onDisappear {
print("Child \(id) onDisappear")
}
}
}
کنسول آؤٹ پٹ: Child B onDisappear, Child A onDisappear, Parent onDisappear — آخر میں۔ onAppear کے مقابلے میں الٹی ترتیب صفائی کی صحیح زنجیر کو یقینی بناتی ہے۔
کال منظرنامے onDisappear کے کنٹینر کی قسم پر منحصر ہیں۔ NavigationStack میں، onDisappear pop-to-root، عام pop-back یا سوائپ (interactivePopGestureRecognizer) کے ذریعے اسکرین مسترد کرنے پر متحرک ہوتا ہے۔ TabView میں، ٹیب تبدیل کرنے سے پوشیدہ ٹیب کے لیے onDisappear اور دکھائے گئے ٹیب کے لیے onAppear کال ہوتا ہے — دونوں موڈیفائر تقریباً ایک ساتھ متحرک ہوتے ہیں۔
Sheet اور fullScreenCover میں، onDisappear پروگراماتی مسترد کرنے (@Environment(\.dismiss) کے ذریعے) یا نیچے کی طرف سوائپ جیسچر پر کال ہوتا ہے۔ ایک اہم تفصیل: اگر sheet کھلا تھا لیکن صارف نے ایپ تبدیل کی، تو onDisappear اصل بند ہونے تک کال نہیں ہوتا۔
| منظرنامہ | onDisappear کال ہوتا ہے | نوٹ |
|---|---|---|
| NavigationStack میں Pop | ہاں | اینیمیشن کے فوراً بعد |
| TabView ٹیب تبدیل | ہاں | موجودہ ٹیب |
| Sheet مسترد کرنا | ہاں | اینیمیشن مکمل ہونے سے پہلے |
| List میں اسکرول | ہاں | سیل پری فیچ زون سے باہر |
| ایپ کو چھوٹا کرنا | نہیں | کال کی کوئی ضمانت نہیں |
| کریش/watchdog kill | نہیں | کال نہیں ہوتا |
استعمال کے اہم معاملات onDisappear کے وسائل کی صفائی، حالت محفوظ کرنا اور ٹریکنگ ہیں۔ onAppear کے برعکس، onDisappear کے کام خارج ہونے پر انجام پاتے ہیں اور انہیں نقل کی جانچ کی ضرورت نہیں ہوتی کیونکہ View ایک بار غائب ہوتا ہے۔
حالت محفوظ کرنا onDisappear میں خاص طور پر فارمز کے لیے مفید ہے جہاں اسکرین چھوڑتے وقت ڈیٹا محفوظ کرنا ضروری ہے۔ ٹائمر اور Combine سبسکرپشنز onDisappear میں منسوخ کی جاتی ہیں تاکہ اسکرین پر واپس آنے پر رساو سے بچا جا سکے۔
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")
}
}
ٹائمر منسوخ کرنا onDisappear میں اسکرین بند ہونے کے بعد کوڈ کے عمل کو روکتا ہے۔ منسوخی کے بغیر، ٹائمر @State کو اپ ڈیٹ کرنے کی کوشش کر سکتا ہے جو اب موجودہ View سے تعلق نہیں رکھتا، جس سے رن ٹائم وارننگ پیدا ہوتی ہے۔
اسکرین پر قیام کا وقت ایک کلاسک ٹریکنگ منظرنامہ ہے۔ onAppear میں وقت ریکارڈ کریں، onDisappear میں فرق کا حساب لگائیں اور سیشن کی مدت کے ساتھ ایک تجزیاتی واقعہ بھیجیں۔
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)
])
}
}
}
}
اہم فرق onDisappear اور onAppear کے درمیان کال کی ترتیب اور عملدرآمد کی ضمانتیں ہیں۔ onAppear View کو درجہ بندی میں شامل کرنے پر کال ہوتا ہے اور دوبارہ تخلیق پر دوبارہ کال ہو سکتا ہے۔ onDisappear ہٹانے پر کال ہوتا ہے اور صرف عام بندش پر متحرک ہونے کی ضمانت ہے، کریش منظرناموں میں نہیں۔
WWDC 2024 کے مطابق، Apple onDisappear کو صفائی کے نقطہ کے طور پر علاج کرنے کی سفارش کرتا ہے، ڈیٹا کمٹ پوائنٹ کے طور پر نہیں۔ اہم ڈیٹا (ادائیگیاں، رجسٹریشن) ریئل ٹائم میں محفوظ کیا جانا چاہیے، View کے غائب ہونے کے لمحے نہیں، کیونکہ ایپ کو چھوٹا کرنے پر onDisappear کی ضمانت نہیں ہے۔
| خصوصیت | .onAppear | .onDisappear |
|---|---|---|
| کال کا لمحہ | View درجہ بندی میں شامل | View درجہ بندی سے ہٹایا گیا |
| ترتیب | Parent-first | Child-first |
| ضمانت | اعلیٰ | کریش پر نہیں |
| اہم کام | ابتداء | صفائی |
| بار بار کال | View دوبارہ تخلیق پر | فی غائب ہونا ایک بار |
سفارش: onDisappear کو صرف غیر اہم صفائی اور ٹریکنگ کے لیے استعمال کریں۔ ڈیٹا کی پائیداری کے لیے AppDelegate میں scenePhase یا applicationWillTerminate اطلاعات استعمال کریں۔
منظرنامہ 1: YouTube جیسی پلے بیک. ویڈیو کی تفصیلات کی اسکرین پر، onDisappear UserDefaults میں پلے بیک پوزیشن محفوظ کرتا ہے۔ دوبارہ کھلنے پر، onAppear UserDefaults سے پوزیشن بحال کرتا ہے، جو مسلسل دیکھنے کا تجربہ فراہم کرتا ہے۔
منظرنامہ 2: Combine سبسکرپشن منسوخ کرنا. اگر ViewModel Combine پبلشرز استعمال کرتا ہے، تو onDisappear cancellable?.cancel() کے ذریعے سبسکرپشن منسوخ کرتا ہے۔ یہ اسکرین چھوڑنے کے بعد UI اپ ڈیٹس کو روکتا ہے، جو پیجینیشن والی فہرستوں اور تلاش کی استفسارات کے لیے خاص طور پر اہم ہے۔
منظرنامہ 3: WebSocket بند کرنا. ریئل ٹائم کنکشن والی ایپس (میسنجر، کوٹیشن فیڈ) میں، onDisappear بیٹری اور ڈیٹا بچانے کے لیے WebSocket کنکشن بند کرتا ہے۔ اسکرین پر واپسی پر onAppear میں دوبارہ کنکشن ہوتا ہے۔
WebSocket ایک عام وسیلہ ہے جسے اسکرین چھوڑتے وقت بند کرنے کی ضرورت ہے۔ نیچے دی گئی مثال میں، onDisappear ساکٹ کو منقطع کرتا ہے اور onAppear دوبارہ منسلک کرتا ہے، جو متعدد اسکرینوں والی ایپس کے لیے نمایاں ڈیٹا بچت فراہم کرتا ہے۔
struct ChatView: View {
@StateObject private var socket = WebSocketManager()
var body: some View {
ChatListView(messages: socket.messages)
.onAppear {
socket.connect()
}
.onDisappear {
socket.disconnect()
}
}
}
اہم: TabView ٹیبز کے درمیان سوئچ کرتے وقت، موجودہ ٹیب کا onDisappear اور اگلے ٹیب کا onAppear تقریباً ایک ساتھ متحرک ہوتے ہیں۔ WebSocket کے لیے یہ منقطع-دوبارہ منسلک سائیکل کا سبب بن سکتا ہے جو غیر ضروری بوجھ پیدا کرتا ہے۔ حل یہ ہے کہ تاخیر استعمال کریں یا چیک کریں کہ آیا اگلی اسکرین پر ساکٹ کی ضرورت ہے۔
اکثر پوچھے گئے سوالات
ہاں، .onDisappear ایپ کریش (crash, watchdog kill)، اسکرین بند کیے بغیر ایپ کو چھوٹا کرنے یا سسٹم منظرناموں میں جہاں ایپ پس منظر میں ختم ہو جاتی ہے، کال کی ضمانت نہیں دیتا۔ اہم ڈیٹا کے لیے scenePhase یا applicationWillTerminate استعمال کریں۔
.onDisappear View کو درجہ بندی سے ہٹائے جانے پر متحرک ہوتا ہے — ایک مخصوص اسکرین کے لیے مقامی کال بیک۔ .scenePhase (@Environment(\.scenePhase) کے ذریعے) پوری ایپ کی حالت بدلنے پر متحرک ہوتا ہے: active, inactive, background۔ اسکرین وقت کی ٹریکنگ کے لیے onAppear+onDisappear اور عالمی حالت کی پائیداری کے لیے scenePhase استعمال کریں۔
وجہ تیز ٹیب سوئچنگ یا ایک ہی اسکرین کا بار بار push/pop ہے۔ SwiftUI ایک نیا View مثال بنا سکتا ہے، پرانے کو ہٹا سکتا ہے، دوبارہ بنا سکتا ہے — ہر بار onDisappear اور onAppear کال کرتا ہے۔ چیک کریں کہ آیا آپ .id()، .equatable() استعمال کر رہے ہیں یا پیرنٹ body میں View دوبارہ بنا رہے ہیں۔
ہاں، .onDisappear macOS (10.15+) پر یکساں رویے کے ساتھ مکمل طور پر سپورٹ کیا جاتا ہے: ونڈو بند کرنے، split view پینل ہٹانے یا موڈل مسترد کرنے پر کال ہوتا ہے۔ macOS پر، onDisappear ونڈو چھپانے پر بھی کال ہوتا ہے (صرف بند کرنے پر نہیں)، جو macOS ایپس کے لیے غور کرنا اہم ہے۔
@State میں URLSessionTask کا حوالہ محفوظ کریں اور onDisappear میں task.cancel() کال کریں۔ متبادل طور پر، .task موڈیفائر استعمال کریں جو View غائب ہونے پر خود بخود async آپریشن منسوخ کر دیتا ہے۔ .task URLSession سمیت تمام async آپریشنز کے لیے ترجیح دی جاتی ہے۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں