.onAppear একটি SwiftUI মডিফায়ার যা View ইন্টারফেস হায়ারার্কিতে যোগ করার সময় ক্লোজার নির্বাহ করে। কল স্ক্রিনে ইনস্ট্যান্সের উপস্থিতিতে একবার ঘটে এবং ডেটা লোড, অ্যানিমেশন শুরু এবং অ্যানালিটিক্স ইভেন্ট পাঠানোর প্রধান পয়েন্ট হিসেবে কাজ করে। Apple Developer Documentation (2026) অনুসারে, onAppear প্রথম রেন্ডারের আগে নির্বাহের গ্যারান্টি দেয়, কিন্তু View মেমরিতে থাকলে প্রতিটি পুনরাবৃত্ত প্রদর্শনে কলের গ্যারান্টি দেয় না। SwiftUI সম্পর্কে আরও পড়ুন SwiftUI নিবন্ধে।
মূল পয়েন্ট
.onAppear SwiftUI-তে একটি View মডিফায়ার যা Void ক্লোজার নেয় এবং View স্ক্রিনে দৃশ্যমান হলে তা নির্বাহ করে। এই মডিফায়ারটি .onDisappear এবং .task-এর সাথে SwiftUI কম্পোনেন্ট জীবনচক্র সিস্টেমের অংশ। Apple UIKit-এর viewDidLoad-এর প্রতিস্থাপন হিসেবে SwiftUI-র iOS 13 এবং watchOS 6 রিলিজের সাথে onAppear চালু করে।
বাক্যগঠনের দিক থেকে, .onAppear যেকোনো View পরিবর্তন করে এবং সংযুক্ত কর্মসহ একই View ফেরত দেয়। SwiftUI কম্পোজার পাস করা ক্লোজারটি একবার কল করে যখন View হায়ারার্কিতে যোগ হয় এবং রেন্ডারিং ধাপ অতিক্রম করে। যদি View সরানো হয় এবং পুনরায় যোগ করা হয় (উদাহরণস্বরূপ, তালিকায় স্ক্রোল করার সময়), onAppear পুনরায় কল হয় — এই আচরণ প্রায়ই অপ্রত্যাশিত বাগের উৎস হয়।
মডিফায়ারের মৌলিক সিনট্যাক্স ন্যূনতম: প্যারামিটার ছাড়া onAppear। SwiftUI-তে অগ্রাধিকার বা অ্যানিমেশন পাস করার কোনো উপায় নেই — ক্লোজার রেন্ডারিংয়ের পরপরই মূল থ্রেডে সিঙ্ক্রোনাসভাবে নির্বাহ হয়।
struct ContentView: View {
var body: some View {
Text("Hello, SwiftUI!")
.onAppear {
print("View appeared on screen")
}
}
}
সীমাবদ্ধতা: onAppear সরাসরি async/await সমর্থন করে না। ক্লোজারের ভিতরে অ্যাসিঙ্ক্রোনাস অপারেশনের জন্য Task {} বা Task.detached-এর মাধ্যমে কল করা আলাদা async/await ফাংশন প্রয়োজন। এটি onAppear-কে .task মডিফায়ারের তুলনায় নেটওয়ার্ক অনুরোধের জন্য কম সুবিধাজনক করে তোলে।
.onAppear layout+render ধাপে SwiftUI রেন্ডারিং পাইপলাইনে এম্বেডেড। যখন SwiftUI View বডি গণনা করে এবং হায়ারার্কি পরিবর্তন শনাক্ত করে, তখন এটি সমস্ত নতুন যোগ করা View-এর জন্য onAppear কলব্যাক চালায়। কল ক্রম নেস্টিং অনুসরণ করে: প্রথমে প্যারেন্ট onAppear, তারপর চাইল্ড উপাদান।
SwiftUI-র একটি গুরুত্বপূর্ণ বৈশিষ্ট্য হল onAppear ভৌত স্ক্রিন উপস্থিতির সাথে আবদ্ধ নয়। View হায়ারার্কিতে যোগ হলে মডিফায়ার কল হয়, তা ব্যবহারকারীর কাছে দৃশ্যমান হোক বা না হোক (উদাহরণস্বরূপ, ScrollView-এ স্ক্রিনের বাইরে)। এটি SwiftUI-কে UIKit থেকে আলাদা করে, যেখানে viewWillAppear শুধুমাত্র প্রকৃত উপস্থিতিতে চলে।
কল ক্রম প্যারেন্ট-ফার্স্ট নিয়ম অনুসরণ করে: VStack বা NavigationView প্রথমে onAppear পায়, তারপর ক্রমে প্রতিটি চাইল্ড উপাদান। এটি শেয়ার্ড রিসোর্স ইনিশিয়ালাইজেশনের জন্য গুরুত্বপূর্ণ: যদি চাইল্ড উপাদান প্যারেন্টের লোড করা ডেটার উপর নির্ভর করে, তবে তাদের Optional-এর মাধ্যমে উপলব্ধতা পরীক্ষা করতে হবে।
struct ParentView: View {
var body: some View {
VStack {
ChildView()
ChildView()
}
.onAppear {
print("Parent onAppear — first")
}
}
}
struct ChildView: View {
var body: some View {
Text("Child")
.onAppear {
print("Child onAppear")
}
}
}
কনসোল আউটপুট হবে: Parent onAppear — প্রথমে, তারপর দুবার Child onAppear ক্রমানুসারে। এই আচরণ Apple-এর দ্বারা নিশ্চিত এবং সব SwiftUI সংস্করণে (iOS 13–18) স্থিতিশীল।
.onAppear-এর বেশ কিছু কল পরিস্থিতি আছে যা কন্টেইনার এবং নেভিগেশনের উপর নির্ভর করে। NavigationStack-এ, onAppear নতুন কন্ট্রোলারের প্রতিটি push-এ এবং pop-এ — রুট কন্ট্রোলারের জন্য চলে। TabView-এ, ট্যাব সুইচ করলে প্রদর্শিত ট্যাবের জন্য onAppear এবং লুকানো ট্যাবের জন্য onDisappear কল হয়।
List এবং ScrollView-এ, onAppear সেই সেলগুলির জন্য কল হয় যা দৃশ্যমান এলাকায় প্রবেশ করেছে বা প্রি-রেন্ডারিং বাফারে আছে। iOS 18 একটি প্রিফেচ মেকানিজম চালু করেছে যা স্ক্রোলের 2–3 স্ক্রিন আগে সেলগুলির জন্য onAppear কল করতে পারে — এটি উপলব্ধি গতি বাড়ায় কিন্তু অপ্রয়োজনীয় নেটওয়ার্ক অনুরোধ ট্রিগার করতে পারে।
NavigationStack (iOS 16+) NavigationView-এর চেয়ে ভিন্নভাবে স্ক্রিন স্ট্যাক পরিচালনা করে। নতুন স্ক্রিন push করার সময়, onAppear শুধুমাত্র নতুন স্ক্রিনে চলে, যখন বর্তমান স্ক্রিন প্রকৃত অপসারণ পর্যন্ত onDisappear পায় না। pop-এ, বিপরীত প্রক্রিয়া ঘটে: ছেড়ে যাওয়া স্ক্রিনে onDisappear, ফিরে আসা স্ক্রিনে onAppear।
| পরিস্থিতি | onAppear | onDisappear |
|---|---|---|
| Push | নতুন স্ক্রিন | না (স্ক্রিন স্ট্যাকে থাকে) |
| Pop | ফিরে আসা স্ক্রিন | ছেড়ে যাওয়া স্ক্রিন |
| ট্যাব সুইচ | নতুন ট্যাব | পুরনো ট্যাব |
| শীট বন্ধ | প্যারেন্ট স্ক্রিন | খোলা শীট |
ব্যবহারিক প্রয়োগ onAppear তিনটি প্রধান বিভাগ কভার করে: ডেটা লোডিং, অ্যানিমেশন শুরু করা এবং অ্যানালিটিক্স পাঠানো। ডুপ্লিকেট কল এবং মেমরি লিক এড়াতে প্রতিটি পরিস্থিতিতে SwiftUI জীবনচক্র বৈশিষ্ট্য বিবেচনা করা প্রয়োজন।
ডেটা লোড করা onAppear-এর সবচেয়ে সাধারণ ব্যবহার। ক্লোজারের ভিতরে, async কলের জন্য একটি Task তৈরি হয় এবং ফলাফল @State বা @StateObject-এ সংরক্ষিত হয়। isLoading ফ্ল্যাগ বা nil পরীক্ষা ব্যবহার করে ডেটা আগে লোড হয়েছে কিনা তা যাচাই করা গুরুত্বপূর্ণ।
struct ProfileView: View {
@StateObject private var viewModel = ProfileViewModel()
var body: some View {
VStack {
if viewModel.isLoading {
ProgressView()
} else {
Text(viewModel.userName)
}
}
.onAppear {
guard viewModel.userName == nil else { return }
Task {
await viewModel.loadProfile()
}
}
}
}
পুনরায়-fetch-এর বিরুদ্ধে সুরক্ষা একটি গুরুত্বপূর্ণ অভ্যাস। যদি SwiftUI View পুনরায় তৈরি করে (উদাহরণস্বরূপ, স্ক্রিন ঘূর্ণনে), onAppear সুরক্ষা ছাড়া আবার চলবে। একটি বিকল্প হল .task মডিফায়ার, যা স্বয়ংক্রিয়ভাবে পূর্ববর্তী অনুরোধ বাতিল করে।
প্রবেশ অ্যানিমেশন withAnimation বা animation মডিফায়ারের মাধ্যমে অ্যানিমেশন ট্রিগার করা স্টেট ভেরিয়েবল পরিবর্তন করতে onAppear ব্যবহার করে। সাধারণ প্যাটার্ন: প্রাথমিক অবস্থা (opacity 0, offset 100), উপস্থিতিতে চূড়ান্ত অবস্থায় (opacity 1, offset 0) রূপান্তর।
struct AnimatedCard: View {
@State private var isVisible = false
var body: some View {
RoundedRectangle(cornerRadius: 12)
.fill(Color.blue)
.opacity(isVisible ? 1 : 0)
.offset(y: isVisible ? 0 : 50)
.animation(.spring(), value: isVisible)
.onAppear {
withAnimation(.spring().delay(0.3)) {
isVisible = true
}
}
}
}
0.3 সেকেন্ডের বিলম্ব ক্রমিক উপস্থিতির প্রভাব তৈরি করে যদি স্ক্রিনে একাধিক কার্ড থাকে। অ্যানিমেটেড উপাদানের তালিকার জন্য, বিলম্ব গুণক হিসেবে উপাদান সূচক ব্যবহার করুন।
.task iOS 15-এ যোগ করা একটি SwiftUI মডিফায়ার যা onAppear-এ async অপারেশনের সমস্যা সমাধান করে। onAppear-এর বিপরীতে, .task একটি async ক্লোজার গ্রহণ করে, স্বয়ংক্রিয়ভাবে এর জীবনচক্র পরিচালনা করে এবং View অদৃশ্য হলে তা বাতিল করে। যেখানে onAppear সিঙ্ক্রোনাসভাবে নির্বাহ হয়, .task একটি অ্যাসিঙ্ক্রোনাস অপারেশন শুরু করে এবং SwiftUI-কে onDisappear-এ তা বাতিল করতে দেয়।
প্রধান পার্থক্য হল বাতিল ব্যবস্থাপনা। যখন .task একটি async অপারেশন তৈরি করে, SwiftUI Task-এর একটি রেফারেন্স সংরক্ষণ করে এবং View হায়ারার্কি থেকে সরানো হলে স্বয়ংক্রিয়ভাবে cancel() কল করে। ভিতরে Task {} সহ onAppear চলমান অপারেশন বাতিল করে না — এটি View অদৃশ্য হওয়ার পরও নির্বাহ হতে থাকে, যা রেস কন্ডিশন বা ডিলোকেটেড ইনস্ট্যান্সে লেখার কারণ হতে পারে।
| বৈশিষ্ট্য | .onAppear | .task |
|---|---|---|
| iOS সংস্করণ | iOS 13+ | iOS 15+ |
| Async সমর্থন | শুধুমাত্র Task {} এর মাধ্যমে | মূল async/await |
| স্বয়ংক্রিয় বাতিল | না | View অদৃশ্য হলে |
| পুনরায় কল | প্রতি উপস্থিতিতে | ডিফল্টভাবে একবার |
| সিঙ্ক্রোনাস কোড | হ্যাঁ | শুধুমাত্র async |
মডিফায়ার নির্বাচন: সিঙ্ক্রোনাস কাজের (অ্যানিমেশন, অ্যানালিটিক্স, লগিং) জন্য onAppear ব্যবহার করুন। async ডেটা লোডিং-এর (API, Core Data, ফাইল সিস্টেম) জন্য .task পছন্দ করুন — এটি নিরাপদ এবং পরিষ্কার।
ভুল 1: View পুনর্নির্মাণের কারণে একাধিক কল। যখন SwiftUI View বডি পুনরায় তৈরি করে (স্টেট পরিবর্তন, স্ক্রিন ঘূর্ণন), onAppear আবার কল হতে পারে। সমাধান — লোডিং ফ্ল্যাগ যোগ করুন বা অপ্রয়োজনীয় পুনঃআঁকা রোধ করতে .equatable() ব্যবহার করুন। SwiftLee (2025) অনুসারে, প্রোডাকশনে 40% SwiftUI বাগ onAppear-এর পুনরাবৃত্ত কলের সাথে সম্পর্কিত।
ভুল 2: শক্তিশালী রেফারেন্সের মাধ্যমে মেমরি লিক। যদি onAppear ক্লোজার দুর্বল রেফারেন্স ছাড়া self ক্যাপচার করে, এটি View-এর সাথে রিটেইন সাইকেল তৈরি করে। SwiftUI View অদৃশ্য হলে ক্যাপচার করা অবজেক্টের শূন্যকরণের গ্যারান্টি দেয় না। ViewModel বা সার্ভিসের জন্য ক্যাপচার লিস্ট [weak self] ব্যবহার করুন।
ভুল 3: ব্যাকগ্রাউন্ড থ্রেডে নির্বাহ। onAppear মূল থ্রেডে নির্বাহ হয় — এটি UI অপারেশনের জন্য সঠিক। কিন্তু আপনি যদি onAppear-এর ভিতরে Task শুরু করেন, নিশ্চিত করুন যে @State আপডেট MainActor.run-এর মাধ্যমে হয়। Swift 5.9 এবং উপরে স্বয়ংক্রিয়ভাবে MainActor-এ ফেরত আসে, কিন্তু @MainActor স্পষ্টভাবে উল্লেখ করা ভাল।
লোডিং ফ্ল্যাগ সহ প্যাটার্ন ডুপ্লিকেশন থেকে রক্ষার সবচেয়ে নির্ভরযোগ্য উপায়। ফ্ল্যাগ @State বা @StateObject-এ সংরক্ষণ করুন এবং শুধুমাত্র ম্যানুয়াল আপডেটে রিসেট করুন। একটি বিকল্প onAppear-এর বদলে .task ব্যবহার করা: .task ডিফল্টভাবে পুনঃআঁকার সময় পুনরায় শুরু হয় না যদি async অপারেশন ইতিমধ্যে চলছে।
struct SafeView: View {
@State private var hasAppeared = false
@State private var items: [Item] = []
var body: some View {
List(items, id: \.id) { item in
Text(item.name)
}
.onAppear {
guard !hasAppeared else { return }
hasAppeared = true
Task {
items = await DataService.shared.fetchItems()
}
}
}
}
প্রায়শই জিজ্ঞাসিত প্রশ্ন
viewDidLoad UIViewController-এর জীবনকালে একবার কল হয়, দৃশ্যমানতা নির্বিশেষে। .onAppear প্রতিবার কল হয় যখন View হায়ারার্কিতে যোগ হয় — যদি View সরানো হয় এবং পুনরায় যোগ করা হয়, onAppear আবার চলে। NavigationView-তে, viewDidLoad ইনিশিয়ালাইজেশনের সময় কল হয়, যেখানে onAppear প্রতিটি স্ক্রিন প্রদর্শনে কল হয়।
হ্যাঁ, Task { await asyncFunction() } র্যাপারের মাধ্যমে। তবে, async অপারেশনের জন্য .task পছন্দনীয়, যা স্বয়ংক্রিয়ভাবে বাতিল ব্যবস্থাপনা করে এবং ম্যানুয়ালি Task তৈরি করতে হয় না। .task View অদৃশ্য হলে বাতিলের গ্যারান্টি দেয়, লিক প্রতিরোধ করে।
কারণ @State, @Published, বা পূর্বপুরুষ কনফিগারেশনে পরিবর্তনের কারণে View বডি পুনর্নির্মাণ। SwiftUI যেকোনো পর্যবেক্ষণযোগ্য বৈশিষ্ট্যের পরিবর্তনের প্রতিক্রিয়ায় View পুনরায় আঁকতে পারে। অতিরিক্তভাবে, LazyVStack এবং List দৃশ্যমান এলাকার কাছে আসা সেলগুলির জন্য onAppear কল করে এবং উপরে স্ক্রোল করার সময় পুনরায় কল করে।
হ্যাঁ, .onAppear সব SwiftUI প্ল্যাটফর্মে উপলব্ধ: iOS 13+, watchOS 6+, tvOS 13+, macOS 10.15+. আচরণ একই: View হায়ারার্কিতে যোগ হলে মডিফায়ার কল হয়। watchOS-এ, onAppear অ্যাপ স্ট্যান্ডবাই অবস্থা থেকে সক্রিয় হলে চলে, যা ডিজাইনে বিবেচনা করা প্রয়োজন।
.onAppear প্যারামিটার গ্রহণ করে না — শুধুমাত্র Void ক্লোজার। প্যারামিটার পাস করতে, একটি ক্লোজার ব্যবহার করুন যা বাইরের ভেরিয়েবল ক্যাপচার করে। একটি বিকল্প পদ্ধতি হল ViewModifier বা .onChange-এর সমতুল্যের মাধ্যমে প্যারামিটারসহ কাস্টম onAppear মডিফায়ার তৈরি করা।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন