.onAppear: اصل کار، چرخه عمر و مثال‌هایی در SwiftUI

نویسنده: IT Sectr منتشر شده: 2026-06-26 زمان مطالعه: 10 دقیقه

.onAppear — مودیفیکاتور SwiftUI که بسته را هنگام افزودن View به سلسله‌مراتب رابط اجرا می‌کند. فراخوانی به‌ازای ظهور نمونه در صفحه نمایش یکبار انجام می‌شود و به عنوان نقطه اصلی برای بارگیری داده‌ها، شروع انیمیشن‌ها و ارسال رویدادهای تحلیلی عمل می‌کند. به گزارش Apple Developer Documentation (2026)، onAppear اجرا را قبل از تصویرسازی اول تضمین می‌کند، اما در صورتی که View در حافظه باقی بماند، فراخوانی را در هر نمایش مجدد تضمین نمی‌کند. درباره SwiftUI در مطلب SwiftUI بیشتر بخوانید.

نکات کلیدی

  • .onAppear — مودیفیکاتور SwiftUI برای اجرای کد در زمان ظهور View در صفحه نمایش.
  • یکبارگی — onAppear یک بار در چرخه عمر View فراخوانده می‌شود، اگر در حافظه باقی بماند.
  • بارگیری داده‌ها — سناریو اصلی onAppear: واکشی از API، خواندن از Core Data یا UserDefaults.
  • انیمیشن‌ها — onAppear انیمیشن‌های ورود را آغاز می‌کند: opacity، scale، offset با تاخیر.
  • تحلیل — از طریق onAppear رویدادهای screen view، impression، page open ارسال می‌شوند.

.onAppear چیست؟

.onAppear — مودیفیکاتور View در SwiftUI است که بسته Void را می‌پذیرد و در لحظه‌ای که View روی صفحه نمایش قابل دیدن می‌شود، آن را اجرا می‌کند. این مودیفیکاتور بخشی از سیستم چرخه عمر کامپوننت‌های SwiftUI در کنار .onDisappear و .task است. Apple onAppear را همراه با انتشار SwiftUI در iOS 13 و watchOS 6 به عنوان جایگزین viewDidLoad از UIKit معرفی کرد.

.onAppear از نظر نحوی هر Viewی را تغییر می‌دهد و همان View را با عمل متصل بازمی‌گرداند. کامپایلر SwiftUI بسته ارسالی را یک بار هنگامی که نمایش به سلسله‌مراتب اضافه و مرحله تصویرسازی را طی کند، فراخوان می‌کند. اگر View حذف و سپس مجدداً اضافه شود (مثلاً در پیمایش لیست)، onAppear مجدداً فراخوانده می‌شود — این رفتار اغلب منبع ایجاد باگ‌های پیش‌بی‌نی می‌شود.

انتظار onAppear

انتظار پایه مودیفیکاتور حداقلی است: onAppear بدون پارامتر. در SwiftUI امکان پاسخ اولویت یا انیمیشن وجود ندارد — بسته بلافاصله پس از تصویرسازی در تراکن اصلی به صورت همزمان اجرا می‌شود.

swift
struct ContentView: View {
    var body: some View {
        Text("سلام SwiftUI!")
            .onAppear {
                print("View روی صفحه نمایش ظاهر شد")
            }
    }
}

محدودیت‌ها: onAppear از async/await به صورت مستقیم پشتیبانی نمی‌کند. برای عملیات ناهمزمان درون بسته به Task {} یا یک تابع جداگانه async/await نیاز است که از طریق Task.detached فراخوانده شود. این موضوع onAppear را در مقایسه با مودیفیکاتور .task برای درخواست‌های شبکه کمتر راحت می‌سازد.

.onAppear در چرخه عمر View چگونه کار می‌کند

.onAppear در مرحله layout+render به خط لوله تصویرسازی SwiftUI وارد می‌شود. وقتی SwiftUI بدنه View را محاسبه کرده و تغییر سلسله‌مراتب را کشف کند، فراخوانی‌های onAppear را برای تمام نمایش‌های جدید انجام می‌دهد. ترتیب فراخوانی مطابق ترتیب تودرتونی است: ابتدا onAppear در والد، سپس در المان فرزند.

ویژگی مهم SwiftUI — onAppear به ظهور فیزیکی روی صفحه نمایش وابسته نیست. مودیفیکاتور وقتی فراخوانده می‌شود که View به سلسله‌مراتب اضافه شود، خردوش برای کاربر قابل دیدن باشد یا نه (مثلاً در ScrollView در خارج از صفحه). این SwiftUI را از UIKit متمایز می‌کند، جایی که viewWillAppear تنها در ظهور واقعی فعال می‌شود.

ترتیب فراخوانی onAppear

ترتیب فراخوانی از قاعده parent-first پیروی می‌کند: VStack یا NavigationView ابتدا onAppear را دریافت می‌کنند، سپس هر عنصر فرزند به ترتیب. این برای مقداردهی منابع مشترک حیاتی است: اگر المان فرزند به داده‌های بارگیری شده توسط والد وابسته است، باید دسترسی را از طریق Optional بررسی کنند.

swift
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 کی فراخوانده می‌شود

.onAppear چند سناریو فراخوانی دارد که به کانتینر و ناوبری بستگی دارد. در NavigationStack onAppear با هر push کنترلر جدید و در pop — برای کنترلر ریشه فعال می‌شود. در TabView تغییر زبانه باعث onAppear برای زبانه نمایش داده شده و onDisappear برای زبانه مخفی می‌شود.

در List و ScrollView onAppear برای سلول‌هایی که وارد محدوده نمایش شده یا در بافر پیش‌تصویرسازی قرار دارند، فراخوانده می‌شود. iOS 18 یک مکانیزم prefetch معرفی کرد که می‌تواند onAppear را برای سلول‌هایی در 2–3 صفحه قبل از پیمایش فراخواند، که ادراک را سریع‌تر می‌کند اما می‌تواند باعث درخواست‌های شبکه غیرضروری شود.

ویژگی‌های فراخوانی در NavigationStack

NavigationStack (iOS 16+) پیشه صفحات را متفاوت از NavigationView مدیریت می‌کند. در push صفحه جدید onAppear تنها در صفحه جدید فعال می‌شود و صفحه فعلی onDisappear را تا حذف واقعی دریافت نمی‌کند. در pop فرآیند معکوس اتفاق می‌افتد: onDisappear در صفحه خارج شونده، onAppear در صفحه بازگشته.

سناریوonAppearonDisappear
Pushصفحه جدیدخیر (صفحه در پیشه باقی می‌ماند)
Popصفحه بازگشتهصفحه خارج شونده
تغییر زبانهزبانه جدیدزبانه قدیمی
بستن sheetصفحه والدsheet باز

مصادیق استفاده از .onAppear

کاربرد عملی onAppear سه دسته اصلی را شامل می‌شود: بارگیری داده‌ها، شروع انیمیشن‌ها و ارسال تحلیل. هر سناریو نیازمند در نظر گرفتن ویژگی‌های چرخه عمر SwiftUI است تا از فراخوانی‌های تکراری و نشت حافظه جلوگیری شود.

بارگیری داده از API

بارگیری داده — رایج‌ترین سناریو onAppear. داخل بسته یک Task برای فراخوانی async ایجاد شده و نتیجه در @State یا @StateObject ذخیره می‌شود. مهم است بررسی کنید که داده‌ها دوباره بارگیری نشوند، با استفاده از پرچم isLoading یا بررسی nil.

swift
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) در ظهور.

swift
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 ثانیه اگر چندین کارت از این نوع در صفحه وجود داشته باشد، اثر ظهور پیاپی ایجاد می‌کند. برای لیست عناصر متحرک، از اندیس عنصر به عنوان ضریب تاخیر استفاده کنید.

.onAppear در مقابل .task — تفاوت چیست

.task — مودیفیکاتور SwiftUI است که در iOS 15 اضافه شده و مشکل عملیات ناهمزمان در onAppear را حل می‌کند. بر خلاف onAppear، .task بسته async را می‌پذیرد، به طور خودکار چرخه عمر آن را مدیریت کرده و در ناپدید شدن View آن را لغو می‌کند. onAppear به صورت همزمان اجرا می‌شود، در حالی که .task یک عملیات ناهمزمان را آغاز کرده و به SwiftUI اجازه می‌دهد آن را در onDisappear لغو کند.

تفاوت اصلی — مدیریت لغو. وقتی .task یک عملیات async ایجاد می‌کند، SwiftUI ارجاعی به Task را نگه داشته و به طور خودکار cancel() را با حذف View از سلسله‌مراتب فراخوان می‌کند. onAppear با Task {} داخلی عملیات شروع شده را لغو نمی‌کند — آن به کار خود ادامه می‌دهد حتی پس از ناپدید شدن View، که می‌تواند منجر به شرایط مسابقه یا نوشتن در یک نمونه آزادشده شود.

ویژگی.onAppear.task
نسخه iOSiOS 13+iOS 15+
پشتیبانی asyncتنها از طریق Task {}اصلی async/await
لغو خودکارخیردر ناپدید شدن View
فراخوانی مجدددر هر ظهورپیش‌فرض یکبار
کد همزمانبلهتنها async

انتخاب مودیفیکاتور: برای عملیات همزمان (انیمیشن‌ها، تحلیل، سبت رویداد) از onAppear استفاده کنید. برای بارگیری ناهمزمان داده (API، Core Data، سیستم پرونده) .task ترجیح دارد — ایمن‌تر و تمیزتر است.

اشتباهات رایج با .onAppear

اشتباه 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 از قبل در حال اجرا است.

swift
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()
            }
        }
    }
}

سوالات متداول

تفاوت .onAppear با viewDidLoad در UIKit چیست؟

viewDidLoad یک بار در طول عمر UIViewController، مستقل از قابل دیدن بودن، فراخوانده می‌شود. .onAppear در هر بار افزودن View به سلسله‌مراتب فراخوانده می‌شود — اگر View حذف و مجدداً اضافه شود، onAppear دوباره فعال می‌شود. در NavigationView viewDidLoad در مقداردهی و onAppear در هر نمایش صفحه فراخوانده می‌شود.

آیا می‌توان یک تابع async را داخل .onAppear فراخواند؟

بله، از طریق پیچون Task { await asyncFunction() }. اما برای عملیات async .task ترجیح دارد، چرا که به طور خودکار لغو را مدیریت کرده و نیازی به ایجاد دستی Task ندارد. .task همچنین لغو را در ناپدید شدن View تضمین کرده و از نشت حافظه جلوگیری می‌کند.

چرا .onAppear چند بار فراخوانده می‌شود؟

دلیل ترمیم مجدد بدنه View به دلیل تغییر @State، @Published یا پیکربندی جدید است. SwiftUI می‌تواند View را در پاسخ به تغییر هر ویژگی مشاهده شده بازسازی کند. علاوه بر این، LazyVStack و List onAppear را برای سلول‌هایی که به محدوده نمایش نزدیک می‌شوند و دوباره در پیمایش به بالا فراخوان می‌کنند.

آیا .onAppear در watchOS و tvOS کار می‌کند؟

بله، .onAppear در تمام پلتفرم‌های SwiftUI موجود است: iOS 13+، watchOS 6+، tvOS 13+، macOS 10.15+. رفتار یکسان است: مودیفیکاتور در زمان افزودن View به سلسله‌مراتب فراخوانده می‌شود. در watchOS onAppear با فعال شدن برنامه از حالت انتظار کار می‌کند، که در طراحی باید در نظر گرفته شود.

چگونه پارامترها را به .onAppear ارسال کنیم؟

.onAppear پارامتر نمی‌پذیرد — تنها بسته Void. برای ارسال پارامترها از بسته‌ای استفاده کنید که متغیرهای خارجی را ضبط می‌کند. روش جایگزین — ایجاد یک مودیفیکاتور سفارشی onAppear با پارامترها از طریق ViewModifier یا مشابه .onChange.

خلاصه

  • .onAppear — مودیفیکاتور SwiftUI برای اجرای کد در زمان افزودن View به سلسله‌مراتب رابط.
  • فراخوانی یکبار — onAppear یک بار در نمونه View فراخوانده می‌شود، اگر در حافظه باقی بماند.
  • ترتیب parent-first — View‌های والد onAppear را زودتر از فرزندان دریافت می‌کنند.
  • سناریوهای اصلی — بارگیری داده‌ها، شروع انیمیشن‌ها، ارسال تحلیل.
  • .task ترجیح دارد برای عملیات async به دلیل لغو خودکار در ناپدید شدن View.
  • بررسی Guard — برای محافظت در برابر فراخوانی‌های تکراری در بازسازی View اجباری است.

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید