.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 বিজ্ঞপ্তি ব্যবহার করুন।
পরিস্থিতি ১: YouTube-এর মতো প্লেব্যাক. ভিডিও বিবরণ স্ক্রিনে, onDisappear UserDefaults-এ প্লেব্যাক অবস্থান সংরক্ষণ করে। পুনরায় খোলার সময়, onAppear UserDefaults থেকে অবস্থান পুনরুদ্ধার করে, যা ধারাবাহিক দেখার অভিজ্ঞতা তৈরি করে।
পরিস্থিতি ২: Combine সাবস্ক্রিপশন বাতিল. যদি ViewModel Combine পাবলিশার ব্যবহার করে, onDisappear cancellable?.cancel()-এর মাধ্যমে সাবস্ক্রিপশন বাতিল করে। এটি স্ক্রিন ছাড়ার পর UI আপডেট প্রতিরোধ করে, যা পেজিনেশন সহ তালিকা এবং সার্চ কোয়েরির জন্য বিশেষভাবে গুরুত্বপূর্ণ।
পরিস্থিতি ৩: 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 সব async অপারেশনের জন্য প্রাধান্য পায়, URLSession সহ।
সারাংশ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন