.onAppear — مودیفیکاتور SwiftUI که بسته را هنگام افزودن View به سلسلهمراتب رابط اجرا میکند. فراخوانی بهازای ظهور نمونه در صفحه نمایش یکبار انجام میشود و به عنوان نقطه اصلی برای بارگیری دادهها، شروع انیمیشنها و ارسال رویدادهای تحلیلی عمل میکند. به گزارش Apple Developer Documentation (2026)، onAppear اجرا را قبل از تصویرسازی اول تضمین میکند، اما در صورتی که View در حافظه باقی بماند، فراخوانی را در هر نمایش مجدد تضمین نمیکند. درباره SwiftUI در مطلب SwiftUI بیشتر بخوانید.
نکات کلیدی
.onAppear — مودیفیکاتور View در SwiftUI است که بسته Void را میپذیرد و در لحظهای که View روی صفحه نمایش قابل دیدن میشود، آن را اجرا میکند. این مودیفیکاتور بخشی از سیستم چرخه عمر کامپوننتهای SwiftUI در کنار .onDisappear و .task است. Apple onAppear را همراه با انتشار SwiftUI در iOS 13 و watchOS 6 به عنوان جایگزین viewDidLoad از UIKit معرفی کرد.
.onAppear از نظر نحوی هر Viewی را تغییر میدهد و همان View را با عمل متصل بازمیگرداند. کامپایلر SwiftUI بسته ارسالی را یک بار هنگامی که نمایش به سلسلهمراتب اضافه و مرحله تصویرسازی را طی کند، فراخوان میکند. اگر View حذف و سپس مجدداً اضافه شود (مثلاً در پیمایش لیست)، onAppear مجدداً فراخوانده میشود — این رفتار اغلب منبع ایجاد باگهای پیشبینی میشود.
انتظار پایه مودیفیکاتور حداقلی است: onAppear بدون پارامتر. در SwiftUI امکان پاسخ اولویت یا انیمیشن وجود ندارد — بسته بلافاصله پس از تصویرسازی در تراکن اصلی به صورت همزمان اجرا میشود.
struct ContentView: View {
var body: some View {
Text("سلام SwiftUI!")
.onAppear {
print("View روی صفحه نمایش ظاهر شد")
}
}
}
محدودیتها: onAppear از async/await به صورت مستقیم پشتیبانی نمیکند. برای عملیات ناهمزمان درون بسته به Task {} یا یک تابع جداگانه async/await نیاز است که از طریق Task.detached فراخوانده شود. این موضوع onAppear را در مقایسه با مودیفیکاتور .task برای درخواستهای شبکه کمتر راحت میسازد.
.onAppear در مرحله layout+render به خط لوله تصویرسازی SwiftUI وارد میشود. وقتی SwiftUI بدنه View را محاسبه کرده و تغییر سلسلهمراتب را کشف کند، فراخوانیهای onAppear را برای تمام نمایشهای جدید انجام میدهد. ترتیب فراخوانی مطابق ترتیب تودرتونی است: ابتدا onAppear در والد، سپس در المان فرزند.
ویژگی مهم SwiftUI — onAppear به ظهور فیزیکی روی صفحه نمایش وابسته نیست. مودیفیکاتور وقتی فراخوانده میشود که View به سلسلهمراتب اضافه شود، خردوش برای کاربر قابل دیدن باشد یا نه (مثلاً در ScrollView در خارج از صفحه). این SwiftUI را از UIKit متمایز میکند، جایی که viewWillAppear تنها در ظهور واقعی فعال میشود.
ترتیب فراخوانی از قاعده parent-first پیروی میکند: VStack یا NavigationView ابتدا onAppear را دریافت میکنند، سپس هر عنصر فرزند به ترتیب. این برای مقداردهی منابع مشترک حیاتی است: اگر المان فرزند به دادههای بارگیری شده توسط والد وابسته است، باید دسترسی را از طریق Optional بررسی کنند.
struct ParentView: View {
var body: some View {
VStack {
ChildView()
ChildView()
}
.onAppear {
print("Parent onAppear — اول")
}
}
}
struct ChildView: View {
var body: some View {
Text("کودک")
.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 یک مکانیزم prefetch معرفی کرد که میتواند onAppear را برای سلولهایی در 2–3 صفحه قبل از پیمایش فراخواند، که ادراک را سریعتر میکند اما میتواند باعث درخواستهای شبکه غیرضروری شود.
NavigationStack (iOS 16+) پیشه صفحات را متفاوت از NavigationView مدیریت میکند. در push صفحه جدید onAppear تنها در صفحه جدید فعال میشود و صفحه فعلی onDisappear را تا حذف واقعی دریافت نمیکند. در pop فرآیند معکوس اتفاق میافتد: onDisappear در صفحه خارج شونده، onAppear در صفحه بازگشته.
| سناریو | onAppear | onDisappear |
|---|---|---|
| Push | صفحه جدید | خیر (صفحه در پیشه باقی میماند) |
| Pop | صفحه بازگشته | صفحه خارج شونده |
| تغییر زبانه | زبانه جدید | زبانه قدیمی |
| بستن sheet | صفحه والد | sheet باز |
کاربرد عملی onAppear سه دسته اصلی را شامل میشود: بارگیری دادهها، شروع انیمیشنها و ارسال تحلیل. هر سناریو نیازمند در نظر گرفتن ویژگیهای چرخه عمر SwiftUI است تا از فراخوانیهای تکراری و نشت حافظه جلوگیری شود.
بارگیری داده — رایجترین سناریو onAppear. داخل بسته یک Task برای فراخوانی async ایجاد شده و نتیجه در @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()
}
}
}
}
Guard against re-fetch — رویه حیاتی. اگر SwiftUI View را مجدداً بسازد (مثلاً در چرخش صفحه)، onAppear بدون guard مجدداً فراخوانده میشود. الترناتیو مودیفیکاتور .task است که درخواست قبلی را خودکار لغو میکند.
انیمیشن ورود از onAppear برای تغییر متغیرهای state استفاده میکند که انیمیشن را از طریق withAnimation یا مودیفیکاتور animation تحریک میکنند. الگوی معمولی: وضعیت اولیه (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 — مودیفیکاتور SwiftUI است که در iOS 15 اضافه شده و مشکل عملیات ناهمزمان در onAppear را حل میکند. بر خلاف onAppear، .task بسته async را میپذیرد، به طور خودکار چرخه عمر آن را مدیریت کرده و در ناپدید شدن View آن را لغو میکند. onAppear به صورت همزمان اجرا میشود، در حالی که .task یک عملیات ناهمزمان را آغاز کرده و به SwiftUI اجازه میدهد آن را در onDisappear لغو کند.
تفاوت اصلی — مدیریت لغو. وقتی .task یک عملیات async ایجاد میکند، SwiftUI ارجاعی به Task را نگه داشته و به طور خودکار cancel() را با حذف View از سلسلهمراتب فراخوان میکند. onAppear با Task {} داخلی عملیات شروع شده را لغو نمیکند — آن به کار خود ادامه میدهد حتی پس از ناپدید شدن View، که میتواند منجر به شرایط مسابقه یا نوشتن در یک نمونه آزادشده شود.
| ویژگی | .onAppear | .task |
|---|---|---|
| نسخه iOS | iOS 13+ | iOS 15+ |
| پشتیبانی async | تنها از طریق Task {} | اصلی async/await |
| لغو خودکار | خیر | در ناپدید شدن View |
| فراخوانی مجدد | در هر ظهور | پیشفرض یکبار |
| کد همزمان | بله | تنها async |
انتخاب مودیفیکاتور: برای عملیات همزمان (انیمیشنها، تحلیل، سبت رویداد) از onAppear استفاده کنید. برای بارگیری ناهمزمان داده (API، Core Data، سیستم پرونده) .task ترجیح دارد — ایمنتر و تمیزتر است.
اشتباه 1: فراخوانی چندگانه به دلیل ترمیم مجدد View. وقتی SwiftUI بدنه View را بازسازی کند (تغییر @State، چرخش صفحه)، onAppear ممکن است مجدداً فراخوانده شود. راه حل — افزودن پرچم بارگیری یا استفاده از .equatable() برای جلوگیری از تصویرسازی های ضمیمه. به گزارش SwiftLee (2025)، 40% از باگهای SwiftUI در تولید مربوط به فراخوانیهای تکراری onAppear است.
اشتباه 2: نشت حافظه از طریق ارجاع قوی. اگر بسته onAppear self را بدون ارجاع ضعیف بگیرد، یک retain cycle با View ایجاد میشود. SwiftUI صفر شدن اشیای گیرنده را در ناپدید شدن View تضمین نمیکند. برای ViewModel یا سرویسها از capture list [weak self] استفاده کنید.
اشتباه 3: اجرا در تراکن پسزمینه. onAppear در تراکن اصلی اجرا میشود — این برای عملیات UI صحیح است. اما اگر داخل onAppear یک Task شروع شود، اطمینان حاصل کنید که بهروزرسانی @State از طریق MainActor.run انجام میشود. Swift 5.9 و بالاتر خودکار به MainActor بازمیگردد، اما بهتر است @MainActor را صریحاً مشخص کنید.
الگو با پرچم بارگیری امنترین راه برای محافظت در برابر تکرار است. پرچم را در @State یا @StateObject ذخیره کنید و آن را تنها در بهروزرسانی دستی بازنشانی کنید. الترناتیو — استفاده از .task به جای onAppear: .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 تضمین کرده و از نشت حافظه جلوگیری میکند.
دلیل ترمیم مجدد بدنه View به دلیل تغییر @State، @Published یا پیکربندی جدید است. SwiftUI میتواند View را در پاسخ به تغییر هر ویژگی مشاهده شده بازسازی کند. علاوه بر این، LazyVStack و List onAppear را برای سلولهایی که به محدوده نمایش نزدیک میشوند و دوباره در پیمایش به بالا فراخوان میکنند.
بله، .onAppear در تمام پلتفرمهای SwiftUI موجود است: iOS 13+، watchOS 6+، tvOS 13+، macOS 10.15+. رفتار یکسان است: مودیفیکاتور در زمان افزودن View به سلسلهمراتب فراخوانده میشود. در watchOS onAppear با فعال شدن برنامه از حالت انتظار کار میکند، که در طراحی باید در نظر گرفته شود.
.onAppear پارامتر نمیپذیرد — تنها بسته Void. برای ارسال پارامترها از بستهای استفاده کنید که متغیرهای خارجی را ضبط میکند. روش جایگزین — ایجاد یک مودیفیکاتور سفارشی onAppear با پارامترها از طریق ViewModifier یا مشابه .onChange.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید