@AppStorage در SwiftUI — چیست، UserDefaults و ذخیره‌سازی تنظیمات

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

@AppStorage در SwiftUI — property wrapper برای کار با UserDefaults که به طور خودکار مقدار را با UI همگام‌سازی می‌کند. هنگام تغییر ویژگی اعلام‌شده از طریق @AppStorage، مقدار جدید فوراً در UserDefaults ذخیره می‌شود و هنگامی که UserDefaults از خارج — توسط ویجت یا افزونه — تغییر می‌کند، View به طور خودکار دوباره ترسیم می‌شود. به گفته Apple Developer Documentation (2025)، @AppStorage از String، Int، Double، Bool، Data، URL و نسخه‌های اختیاری آنها پشتیبانی می‌کند و ذخیره‌سازی واکنشی تنظیمات کاربر را بدون کد نظارت دستی فراهم می‌کند.

نکات اصلی

  • @AppStorage — property wrapper برای کار واکنشی با UserDefaults در SwiftUI
  • ذخیره خودکار — مقدار در هر تغییر در UserDefaults ذخیره می‌شود
  • به‌روزرسانی خودکار UI — View هنگام تغییر UserDefaults از هر منبعی دوباره ترسیم می‌شود
  • انواع پشتیبانی‌شده: String، Int، Double، Bool، Data، URL و نسخه‌های اختیاری
  • مقدار پیش‌فرض در اعلام تنظیم می‌شود و در اولین راه‌اندازی استفاده می‌شود

@AppStorage در SwiftUI چیست؟

@AppStorage یک property wrapper است که توسط Apple در iOS 14 معرفی شده و ویژگی View را به یک کلید در UserDefaults متصل می‌کند. هنگام خواندن ویژگی، SwiftUI مقدار را از UserDefaults بر اساس کلید مشخص‌شده بارگیری می‌کند. هنگام نوشتن — مقدار جدید را ذخیره کرده و به View برای ترسیم مجدد اطلاع می‌دهد.

پیش از ظهور @AppStorage، توسعه‌دهندگان مجبور بودند به صورت دستی UserDefaults را در onAppear بخوانند، در اعلان UserDefaults.didChangeNotification مشترک شوند و @State را در تغییرات به‌روزرسانی کنند. @AppStorage کل چرخه را خودکار می‌کند: اعلام در یک خط جایگزین ۱۵–۲۰ خط کادرساز (boilerplate) می‌شود. علاوه بر این، @AppStorage همگام‌سازی دوطرفه را فراهم می‌کند — اگر مقدار UserDefaults از فرآیند دیگری (مثلاً App Extension یا Widget) تغییر کند، View همچنان به‌روزرسانی دریافت می‌کند.

از نظر معماری، @AppStorage به عنوان DynamicProperty پیاده‌سازی شده است که به SwiftUI اجازه می‌دهد وابستگی‌ها را ردیابی کرده و View را هنگام تغییر مقدار مشاهده‌شده دوباره ترسیم کند. این آن را برای ذخیره تنظیمات کاربر ایده‌آل می‌کند: زبان رابط، فعال/غیرفعال کردن ویژگی‌ها، آخرین تب انتخاب‌شده، نام کاربری.

@AppStorage در مقابل UserDefaults: مقایسه

اگرچه @AppStorage در پس‌زمینه از UserDefaults استفاده می‌کند، رویکردهای کار با ذخیره‌سازی تفاوت اساسی دارند. UserDefaults یک API سطح پایین است که نیاز به مدیریت دستی خواندن، نوشتن و اعلان‌های تغییر دارد. @AppStorage یک انتزاع SwiftUI است که رفتار واکنشی را به صورت آماده ارائه می‌دهد.

UserDefaults برای عملیات یک‌باره مناسب است: بارگیری تنظیمات در شروع برنامه، نوشتن تحلیل، کش کردن توکن‌ها. @AppStorage — برای تنظیماتی که باید UI را به صورت واکنشی به‌روزرسانی کنند: سوئیچ‌های تم، انتخاب زبان، ذخیره وضعیت رابط. استفاده مستقیم از UserDefaults درون View یک ضدالگو است، زیرا View بدون اشتراک اضافی از تغییرات مطلع نمی‌شود.

پارامتر@AppStorageUserDefaults
واکنش‌پذیریخودکارنیاز به اشتراک در اعلان‌ها
کادرساز۱ خط به ازای هر ویژگی۱۵–۲۰ خط به ازای هر ویژگی
انواعString، Int، Double، Bool، Data، URLهمه انواع + اشیاء بایگانی‌شده
انواع سفارشیاز طریق RawRepresentableاز طریق NSKeyedArchiver
App Extensionهمگام‌سازی خودکاراشتراک دستی

برای تنظیمات ساده با UI واکنشی، @AppStorage انتخاب ارجح است. برای داده‌های پیچیده (آرایه‌ها، دیکشنری‌ها، اشیاء سفارشی) از ترکیب UserDefaults با @State و اشتراک دستی در تغییرات استفاده کنید یا برای ذخیره‌سازی ساختاریافته به SwiftData / Core Data مهاجرت کنید.

انواع داده‌های پشتیبانی‌شده

@AppStorage از انواع استانداردی که UserDefaults می‌تواند مستقیماً سریال‌سازی کند پشتیبانی می‌کند: String، Int، Double، Bool، Data، URL. برای هر نوع یک نسخه اختیاری وجود دارد (String?، Int?، Double?، Bool?، Data?، URL?) که امکان تمایز بین «تنظیم نشده» و «مقدار خالی» را فراهم می‌کند.

برای ذخیره انواع سفارشی منطبق با پروتکل RawRepresentable، @AppStorage نیز به طور خودکار کار می‌کند. اگر enum دارای rawValue از نوع String یا Int باشد، می‌توان از آن مستقیماً استفاده کرد: @AppStorage("theme") var theme: AppTheme = .system. SwiftUI به طور خودکار مقدار را از طریق rawValue سریال‌سازی/دسریال‌سازی می‌کند.

swift
enum AppTheme: String {
    case system, light, dark
}

struct SettingsView: View {
    @AppStorage("username") var username: String = "Guest"
    @AppStorage("launchCount") var launchCount: Int = 0
    @AppStorage("isDarkMode") var isDarkMode: Bool = false
    @AppStorage("appTheme") var theme: AppTheme = .system
    @AppStorage("lastOpened") var lastOpened: Date? = nil

    var body: some View {
        Form {
            TextField("Username", text: $username)
            Toggle("Dark mode", isOn: $isDarkMode)
            Text("\(launchCount) بار راه‌اندازی شد")
        }
    }
}

در مثال از انواع مختلف @AppStorage استفاده شده است: String با مقدار پیش‌فرض «Guest»، Int برای شمارنده راه‌اندازی، Bool برای تم تیره، enum AppTheme با rawValue از نوع String و Date? اختیاری برای زمان آخرین باز شدن. هر ویژگی به کلید UserDefaults مشخص‌شده در اولین آرگومان متصل است. مقدار پیش‌فرض زمانی استفاده می‌شود که کلید در اولین راه‌اندازی در ذخیره‌سازی وجود نداشته باشد.

نظارت بر تغییرات Store

یکی از مزایای کلیدی @AppStorage — نظارت خودکار بر تغییرات UserDefaults از هر منبعی است. اگر App Extension یا Widget مقداری را تغییر دهد، @AppStorage در برنامه والد اعلان دریافت کرده و View را دوباره ترسیم می‌کند. این از طریق مکانیسم KVO (Key-Value Observing) حاصل می‌شود که @AppStorage به طور خودکار بر روی UserDefaults.didChangeNotification تنظیم می‌کند.

در عمل این بدان معناست که اگر کاربر تنظیماتی را در Widget تغییر دهد (مثلاً تم تیره را فعال کند)، برنامه بلافاصله این تغییر را دریافت می‌کند. به طور مشابه، همگام‌سازی بین برنامه اصلی و Share Extension، Watch App یا Today Widget کار می‌کند. توسعه‌دهنده نیازی به نوشتن کد برای تبادل داده بین فرآیندی ندارد — @AppStorage این کار را به طور خودکار انجام می‌دهد.

swift
struct ThemeSettingView: View {
    @AppStorage("isDarkMode") var isDarkMode: Bool = false

    var body: some View {
        VStack {
            Toggle("Dark Mode", isOn: $isDarkMode)
                .onChange(of: isDarkMode) { oldValue, newValue in
                    print("حالت تاریک به \(newValue) تغییر کرد")
                }
        }
    }
}

Toggle از طریق @AppStorage به $isDarkMode متصل است. هنگام تغییر، مقدار به طور خودکار در UserDefaults تحت کلید «isDarkMode» ذخیره می‌شود. اصلاح‌کننده .onChange امکان انجام یک اقدام جانبی در هنگام تغییر را فراهم می‌کند — مثلاً ارسال تحلیل یا به‌روزرسانی UI سایر صفحه‌ها. اگر Widget همان کلید را تغییر دهد، @AppStorage نیز onChange را فراخوانی می‌کند و ثبات وضعیت را تضمین می‌کند.

نمونه کد @AppStorage

بیایید یک صفحه تنظیمات کامل برنامه را بررسی کنیم که از @AppStorage برای ذخیره تمام پیکربندی‌ها استفاده می‌کند. فرم شامل بخش‌هایی با انواع مختلف تنظیمات است: فیلدهای متنی، سوئیچ‌ها، شمارنده‌ها — همه مقادیر به طور خودکار در UserDefaults ذخیره می‌شوند.

swift
struct AppSettingsView: View {
    @AppStorage("displayName") var displayName = ""
    @AppStorage("notificationsEnabled") var notificationsEnabled = true
    @AppStorage("maxResults") var maxResults = 25
    @AppStorage("selectedTab") var selectedTab = "home"

    var body: some View {
        NavigationStack {
            Form {
                Section(header: Text("پروفایل")) {
                    TextField("Display name", text: $displayName)
                }

                Section(header: Text("تنظیمات")) {
                    Toggle("Enable notifications",
                           isOn: $notificationsEnabled)
                    Stepper("Max results: \(maxResults)",
                           value: $maxResults,
                           in: 10...100,
                           step: 5)
                }

                Section {
                    Button("بازنشانی تنظیمات") {
                        UserDefaults.standard.removePersistentDomain(
                            forName: Bundle.main.bundleIdentifier!)
                    }
                    .tint(.red)
                }
            }
            .navigationTitle("Settings")
        }
    }
}

فرم شامل چهار ویژگی @AppStorage از انواع مختلف است: String برای نام، Bool برای اعلان‌ها، Int برای تعداد نتایج و String برای تب انتخاب‌شده. همه کنترل‌ها از طریق Binding به ویژگی‌ها متصل هستند ($displayName، $notificationsEnabled و غیره). دکمه «Reset settings» تمام UserDefaults را بازنشانی می‌کند و دامنه برنامه را حذف می‌کند — پس از آن @AppStorage به طور خودکار به مقادیر پیش‌فرض بازمی‌گردد.

همگام‌سازی @AppStorage با App Group

swift
struct SharedSettingsView: View {
    let sharedDefaults = UserDefaults(suiteName: "group.com.example.app")

    @AppStorage("widgetTheme", store: UserDefaults(suiteName: "group.com.example.app")!)
    var widgetTheme: String = "سیستم"

    @AppStorage("widgetColor", store: UserDefaults(suiteName: "group.com.example.app")!)
    var widgetColor: String = "آبی"

    var body: some View {
        Form {
            Picker("Widget theme", selection: $widgetTheme) {
                Text("سیستم").tag("system")
                Text("روشن").tag("روشن")
                Text("تاریک").tag("تاریک")
            }
            Picker("Accent color", selection: $widgetColor) {
                Text("آبی").tag("blue")
                Text("سبز").tag("سبز")
                Text("قرمز").tag("قرمز")
            }
        }
    }
}

برای App Group (ذخیره‌سازی مشترک بین برنامه و افزونه‌ها) @AppStorage پارامتر store: UserDefaults(suiteName:) را می‌پذیرد. مقادیر در یک کانتینر مشترک ذخیره می‌شوند که برای برنامه اصلی، Widget، Watch App و سایر افزونه‌های همان گروه قابل دسترسی است. Widget می‌تواند این تنظیمات را بخواند و هنگام تغییر در برنامه، Widget به طور خودکار از طریق مکانیسم نظارت UserDefaults به‌روزرسانی می‌شود.

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

تفاوت بین @AppStorage و @State چیست؟

@State مقدار را فقط در حافظه ذخیره می‌کند و با راه‌اندازی مجدد برنامه بازنشانی می‌شود. @AppStorage مقدار را در UserDefaults ذخیره می‌کند و در راه‌اندازی بعدی بازیابی می‌کند. از @State برای داده‌های موقت صفحه و از @AppStorage برای تنظیماتی که باید راه‌اندازی مجدد را تحمل کنند استفاده کنید.

آیا می‌توان از @AppStorage با Enum استفاده کرد؟

بله، اگر Enum پروتکل RawRepresentable را با rawValue از نوع String یا Int پیاده‌سازی کند. مثال: @AppStorage("theme") var theme: AppTheme = .system. SwiftUI به طور خودکار enum را از طریق rawValue سریال‌سازی کرده و در بارگیری بازیابی می‌کند.

چگونه تمام مقادیر @AppStorage را پاک کنیم؟

UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!) را برای ذخیره‌سازی استاندارد یا removeObject(forKey:) را برای کلید خاص فراخوانی کنید. پس از پاکسازی، تمام ویژگی‌های @AppStorage به مقادیر پیش‌فرض مشخص‌شده در اعلام بازمی‌گردند.

آیا @AppStorage با App Extensions کار می‌کند؟

بله، برای همگام‌سازی بین برنامه و افزونه‌ها از App Group استفاده کنید: @AppStorage("key", store: UserDefaults(suiteName: "group.com.example.app")!). Widget، Share Extension و Watch App می‌توانند در همان UserDefaults بخوانند و بنویسند و تغییرات به طور خودکار ردیابی می‌شوند.

چه حجم داده‌ای می‌توان در @AppStorage ذخیره کرد؟

@AppStorage از UserDefaults استفاده می‌کند که برای حجم کم داده طراحی شده است: تنظیمات، توکن‌ها، شمارنده‌ها. حد توصیه‌شده — تا ۱۰۰ کیلوبایت به ازای هر برنامه. برای داده‌های ساختاریافته یا حجیم (آرایه‌های اشیاء، فایل‌های چندرسانه‌ای) از SwiftData، Core Data یا سیستم فایل استفاده کنید.

خلاصه

  • @AppStorage — property wrapper برای ذخیره‌سازی واکنشی تنظیمات در UserDefaults
  • ذخیره خودکار و به‌روزرسانی خودکار UI هنگام تغییر مقدار از هر منبعی
  • پشتیبانی از String، Int، Double، Bool، Data، URL و RawRepresentable enums
  • مقدار پیش‌فرض در اعلام تنظیم می‌شود و در اولین راه‌اندازی بازیابی می‌شود
  • App Group امکان همگام‌سازی @AppStorage بین برنامه و افزونه‌ها را فراهم می‌کند
  • UserDefaults فقط برای حجم کم داده مناسب است — تا ۱۰۰ کیلوبایت
  • استفاده کنید از @AppStorage برای تنظیمات کاربر، از @State برای حالت‌های موقت صفحه

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

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

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

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