NSUserDefaults — چیست، UserDefaults API و کار با تنظیمات iOS

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

NSUserDefaults یک فروشگاه داده کلید-مقدار در iOS، watchOS، tvOS و macOS است که برای ذخیره تنظیمات و پیکربندی برنامه طراحی شده است. داده‌ها در فایل plist در sandbox برنامه ذخیره شده و به طور خودکار از طریق NSUbiquitousKeyValueStore با iCloud همگام‌سازی می‌شوند. طبق مستندات رسمی Apple Developer, 2025، NSUserDefaults از ذخیره انواع اولیه پشتیبانی می‌کند: String، Int، Bool، Float، Double، Data، Date، Array و Dictionary. این کلاس از Swift 3 به UserDefaults تغییر نام داده است، اما نام Objective-C آن یعنی NSUserDefaults همچنان در پایگاه کد و مستندات Apple به طور گسترده استفاده می‌شود.

نکات اصلی

  • NSUserDefaults — فروشگاه کلید-مقدار در iOS و macOS برای ذخیره تنظیمات ساده برنامه در فایل plist.
  • از نه نوع داده پشتیبانی می‌کند: String، Int، Bool، Float، Double، Data، Date، Array و Dictionary.
  • داده‌ها به طور خودکار از طریق NSUbiquitousKeyValueStore با iCloud همگام‌سازی می‌شوند.
  • از سیستم ثبت‌ها (دامنه‌ها) با جستجوی آبشاری مقدار در زنجیره دامنه‌ها استفاده می‌کند.
  • برای ذخیره داده‌های حساس، Apple به جای NSUserDefaults استفاده از Keychain را توصیه می‌کند.

NSUserDefaults چیست؟

NSUserDefaults (UserDefaults در Swift) — یک مکانیسم داخلی Apple برای ذخیره جفت‌های کلید-مقدار در قالب plist است. این مکانیسم در تمام پلتفرم‌های Apple در دسترس است: iOS، iPadOS، watchOS، tvOS و macOS. هدف اصلی — ذخیره ترجیحات کاربر، وضعیت رابط، پرچم‌های راه‌اندازی اولیه، گزینه‌های انتخاب شده و سایر داده‌های ساده که پس از راه‌اندازی مجدد برنامه باقی می‌مانند.

هر برنامه iOS یک sandbox ایزوله دارد و NSUserDefaults در پوشه Library/Preferences داخل این sandbox در فایلی با نام Bundle Identifier ذخیره می‌شود. فایل plist شامل جفت‌های کلید-مقدار است که کلید یک رشته و مقدار یکی از انواع پشتیبانی شده است. اندازه فایل محدود نیست، اما Apple توصیه می‌کند فقط تنظیمات را در UserDefaults ذخیره کنید، نه حجم زیادی از داده.

از iOS 8، NSUserDefaults از App Groups پشتیبانی می‌کند — ذخیره‌سازی مشترک بین برنامه‌های یک توسعه‌دهنده و افزونه‌های آنها (ویجت‌ها، برنامه‌های همراه watchOS). برای این کار از مقداردهنده اولیه init?(suiteName:) با شناسه App Group استفاده می‌شود. این به ویجت در صفحه Today اجازه می‌دهد تنظیمات را از برنامه اصلی بدون تکرار منطق ذخیره‌سازی بخواند.

فرمت ذخیره‌سازی: plist روی دستگاه

از نظر فیزیکی، NSUserDefaults در فایل plist باینری در مسیر ذخیره می‌شود: {Sandbox}/Library/Preferences/com.example.myapp.plist. فایل از فرمت plist باینری (NSPropertyListBinaryFormat_v1_0) برای فشردگی و سرعت خواندن استفاده می‌کند. در macOS، فایل می‌تواند برای سازگاری در قالب XML باشد. بر خلاف SharedPreferences در Android، فایل‌های plist UserDefaults می‌توانند ساختارهای تودرتو را از طریق Dictionary و Array شامل شوند.

فایل‌های NSUserDefaults به طور پیش‌فرض رمزگذاری نمی‌شوند. داده‌ها به صورت آشکار ذخیره می‌شوند و با دسترسی فیزیکی به دستگاه یا از طریق پشتیبان‌گیری قابل خواندن هستند. برای ذخیره داده‌های حساس (رمزهای عبور، توکن‌ها، کلیدهای رمزگذاری)، Apple به طور قطعی استفاده از Keychain را توصیه می‌کند که به طور خودکار داده‌ها را در سطح سیستم عامل رمزگذاری می‌کند.

NSUserDefaults در iOS چگونه کار می‌کند

NSUserDefaults بر اساس اصل ذخیره موقت در حافظه با همگام‌سازی دوره‌ای روی دیسک کار می‌کند. در اولین مراجعه به نمونه استاندارد UserDefaults.standard، سیستم فایل plist را به صورت Dictionary در حافظه RAM بارگذاری می‌کند. تمام خوانش‌های بعدی از حافظه انجام می‌شوند. نوشتن نیز ابتدا در حافظه انجام می‌شود و همگام‌سازی روی دیسک به صورت دوره‌ای در پس‌زمینه رخ می‌دهد.

عملیات نوشتن از متد set(_:forKey:) استفاده می‌کند که مقدار اختیاری از نوع Any? را می‌پذیرد. مقدار می‌تواند nil باشد — برای حذف کلید. برای نوشتن فوری روی دیسک قبلاً از متد synchronize() استفاده می‌شد، اما از iOS 7 و OS X 10.9 دیگر نیازی به آن نیست — سیستم به طور خودکار داده‌ها را در فواصل منظم همگام‌سازی می‌کند. Apple رسماً اعلام کرده که synchronize() در مستندات خود زائد است.

ثبت‌های UserDefaults و دامنه‌ها

NSUserDefaults از سیستم ثبت‌ها (دامنه‌ها) برای سازماندهی جستجوی مقادیر استفاده می‌کند. هنگامی که برنامه مقدار را با کلید درخواست می‌کند، UserDefaults به ترتیب دامنه‌ها را به ترتیب مشخص بررسی می‌کند: ابتدا NSArgumentDomain (آرگومان‌های خط فرمان)، سپس دامنه برنامه (Application)، سپس NSGlobalDomain (تنظیمات سیستم)، سپس دامنه‌های خاص زبان و در نهایت NSRegistrationDomain (مقادیر پیش‌فرض ثبت شده از طریق register(defaults:)).

swift
import Foundation

// نمونه استاندارد UserDefaults
let defaults = UserDefaults.standard

// نوشتن مقادیر
defaults.set("آنا پترووا", forKey: "username")
defaults.set(28, forKey: "age")
defaults.set(true, forKey: "isLoggedIn")

// ثبت مقادیر پیش‌فرض
defaults.register(defaults: [
    "theme": "system",
    "fontSize": 14
])

// خواندن با برگرداندن مقدار پیش‌فرض
let theme = defaults.string(forKey: "theme") ?? "system"
let fontSize = defaults.integer(forKey: "fontSize")

دامنه NSRegistrationDomain یک دامنه برنامه‌ای است که فقط در حافظه RAM وجود دارد و روی دیسک ذخیره نمی‌شود. این دامنه برای تنظیم مقادیر پیش‌فرض استفاده می‌شود که تا زمانی که برنامه مقدار خود را در دامنه برنامه ننویسد فعال هستند. این امکان ایجاد یک نقطه پیکربندی واحد برای تنظیمات پیش‌فرض را فراهم می‌کند که می‌توان در مرحله توسعه به صورت متمرکز تغییر داد.

روش‌های اصلی NSUserDefaults

NSUserDefaults مجموعه‌ای از متدهای تایپ‌شده برای خواندن و نوشتن داده‌ها ارائه می‌دهد: string(forKey:)، integer(forKey:)، bool(forKey:)، float(forKey:)، double(forKey:)، data(forKey:)، array(forKey:)، dictionary(forKey:) و object(forKey:). هر متد خواندن یک متد نوشتن متناظر set(_:forKey:) با تعیین خودکار نوع مقدار ذخیره شده دارد. نسخه Swift UserDefaults از تایپ‌سازی دقیق استفاده می‌کند، اما نسخه Objective-C id را می‌پذیرد و برمی‌گرداند.

متد خواندن (Swift)نوع دادهمقدار پیش‌فرض
string(forKey:)String?nil
integer(forKey:)Int0
bool(forKey:)Boolfalse
float(forKey:)Float0.0
double(forKey:)Double0.0
data(forKey:)Data?nil

synchronize و مرتبط بودن آن

متد synchronize() در NSUserDefaults تمام تغییرات را از حافظه به زور روی دیسک می‌نویسد. در نسخه‌های اولیه iOS، این متد باید پس از هر نوشتن برای تضمین ذخیره داده فراخوانی می‌شد. از iOS 7، سیستم به طور خودکار UserDefaults را در پس‌زمینه همگام‌سازی می‌کند و Apple رسماً synchronize() را زائد اعلام کرده است. فراخوانی این متد خطایی ایجاد نمی‌کند، اما هیچ تضمینی برای ذخیره اضافی ارائه نمی‌دهد.

برای نظارت بر تغییرات، NSUserDefaults اعلان UserDefaults.didChangeNotification و متد مشاهده KVO addObserver(_:forKeyPath:options:context:) را ارائه می‌دهد. در SwiftUI، Property Wrapper @AppStorage در دسترس است که به طور خودکار مقدار UserDefaults را با به‌روزرسانی UI همگام‌سازی می‌کند. @AppStorage از همان انواع UserDefaults پشتیبانی می‌کند و روش ترجیحی کار با تنظیمات در برنامه‌های SwiftUI است.

swift
// مشاهده تغییرات از طریق KVO
class SettingsViewModel: NSObject {
    override func observeValue(
        forKeyPath keyPath: String?,
        of object: Any?,
        change: [NSKeyValueChangeKey: Any]?,
        context: UnsafeMutableRawPointer?
    ) {
        guard let keyPath else { return }
        print("کلید تغییر کرد: \(keyPath)")
    }
}

// SwiftUI - AppStorage
struct SettingsView: View {
    @AppStorage("theme") private var theme: String = "system"

    var body: some View {
        Picker("تم", selection: $theme) {
            Text("سیستمی").tag("system")
            Text("روشن").tag("light")
            Text("تاریک").tag("dark")
        }
    }
}

برای کار با App Groups (ذخیره‌سازی مشترک بین برنامه و افزونه‌ها) از مقداردهنده اولیه UserDefaults(suiteName:) با شناسه App Group استفاده می‌شود. به عنوان مثال، "group.com.example.myapp". داده‌های نوشته شده در این نمونه از برنامه اصلی، ویجت، برنامه همراه watchOS و سایر افزونه‌های متعلق به یک App Group قابل دسترسی هستند. هر نمونه suite در یک فایل plist جداگانه ذخیره می‌شود.

NSUserDefaults در مقابل جایگزین‌های ذخیره‌سازی

با وجود راحتی و سادگی، NSUserDefaults یک فروشگاه جهانی برای همه انواع داده در iOS نیست. بسته به حجم، حساسیت و الزامات امنیتی، Apple چندین جایگزین ارائه می‌دهد که هر کدام برای سناریوی استفاده خاص بهینه شده‌اند.

راهکارچه زمانی استفاده شودمحدودیت‌ها
NSUserDefaultsتنظیمات رابط و پیکربندیبرای داده‌های حجیم و اسرار مناسب نیست
Keychainرمزهای عبور، توکن‌ها، کلیدهای رمزگذاریاستفاده پیچیده‌تر، کندتر
CoreDataداده‌های ساختاریافته با روابطبرای 10-20 تنظیم بیش از حد
FileManagerاسناد، تصاویر، داده‌های باینرینیاز به مدیریت دستی فایل‌ها
CloudKitهمگام‌سازی ابری بین دستگاه‌هانیاز به حساب iCloud و اتصال شبکه

Keychain — ذخیره‌سازی امن

Keychain — یک فروشگاه محافظت شده Apple برای داده‌های محرمانه است. بر خلاف NSUserDefaults، تمام داده‌ها در Keychain در سطح سیستم عامل با استفاده از رمزگذاری سخت‌افزاری Secure Enclave در دستگاه‌های سازگار رمزگذاری می‌شوند. Keychain به طور خودکار همراه با دستگاه قفل و باز می‌شود و از اشتراک دسترسی بین برنامه‌های یک توسعه‌دهنده از طریق Keychain Access Groups پشتیبانی می‌کند.

عیب اصلی Keychain — پیچیدگی API است. برای ذخیره ساده یک رشته، باید درخواست SecItemAdd با مشخص کردن ویژگی‌ها ایجاد کنید: کلاس (kSecClassGenericPassword)، سرویس (kSecAttrService)، حساب (kSecAttrAccount) و خود داده (kSecValueData). برای ساده‌سازی کار با Keychain، بسته‌های شخص ثالثی مانند KeychainAccess و SwiftKeychainWrapper وجود دارند که رابط راحت کلید-مقدار مشابه UserDefaults ارائه می‌دهند.

مثال استفاده از NSUserDefaults در Swift

بیایید یک مثال عملی را بررسی کنیم: ذخیره و بازیابی وضعیت راهنما (صفحات خوش‌آمدگویی) در یک برنامه iOS با استفاده از NSUserDefaults. در اولین راه‌اندازی، کاربر صفحات راهنما را می‌بیند، پس از عبور از آنها، پرچم در UserDefaults ذخیره می‌شود. در راه‌اندازی‌های بعدی، راهنما رد می‌شود. برای SwiftUI از @AppStorage استفاده می‌شود، برای UIKit — دسترسی مستقیم به UserDefaults.standard.

ذخیره وضعیت راهنما

مدیری به نام OnboardingManager ایجاد می‌کنیم که کار با UserDefaults را برای ذخیره وضعیت راهنما کپسوله می‌کند. مدیر ویژگی isOnboardingCompleted برای بررسی وضعیت و متد markOnboardingCompleted برای تنظیم پرچم ارائه می‌دهد. کلید ذخیره‌سازی برای جلوگیری از اشتباهات تایپی در یک ثابت قرار گرفته است. برای تست واحد، مدیر از پروتکل UserDefaultsProtocol استفاده می‌کند که امکان جایگزینی فروشگاه واقعی با MockUserDefaults را فراهم می‌کند.

swift
class OnboardingManager {
    private let defaults: UserDefaults
    private let hasSeenKey = "has_seen_onboarding"

    init(defaults: UserDefaults = .standard) {
        self.defaults = defaults
    }

    var isOnboardingCompleted: Bool {
        defaults.bool(forKey: hasSeenKey)
    }

    func markOnboardingCompleted() {
        defaults.set(true, forKey: hasSeenKey)
    }

    func resetOnboarding() {
        defaults.removeObject(forKey: hasSeenKey)
    }
}

// استفاده در برنامه
let onboardingManager = OnboardingManager()
if !onboardingManager.isOnboardingCompleted {
    showOnboarding()
} else {
    showMainScreen()
}

برای ذخیره تنظیمات پیچیده‌تر، مانند یک شیء Profile ساختاریافته، استفاده از پروتکل Codable و JSONEncoder/JSONDecoder توصیه می‌شود. شیء از طریق JSONEncoder به Data سریالایز می‌شود، از طریق set(_:forKey:) ذخیره می‌شود و هنگام خواندن از طریق JSONDecoder از Data دوباره به شیء دیسریالایز می‌شود. این رویکرد امکان ذخیره ساختارهای پیچیده در UserDefaults را بدون از دست دادن ایمنی نوع فراهم می‌کند.

swift
struct UserProfile: Codable {
    let name: String
    let age: Int
    let preferences: [String: String]
}

extension UserDefaults {
    func save<T: Codable>(_ value: T, forKey key: String) {
        if let data = try? JSONEncoder().encode(value) {
            set(data, forKey: key)
        }
    }

    func load<T: Codable>(_ type: T.Type, forKey key: String) -> T? {
        guard let data = data(forKey: key) else { return nil }
        return try? JSONDecoder().decode(type, from: data)
    }
}

// استفاده
let profile = UserProfile(name: "آنا", age: 28, preferences: ["theme": "dark"])
UserDefaults.standard.save(profile, forKey: "user_profile")
let loaded = UserDefaults.standard.load(UserProfile.self, forKey: "user_profile")

مهم است به خاطر داشته باشید که NSUserDefaults برای ذخیره حجم زیادی از داده طراحی نشده است. Apple توصیه می‌کند اندازه داده‌های ذخیره شده را به چند ده کیلوبایت محدود کنید. برای ذخیره اشیاء بزرگ (تصاویر، اسناد، مدل‌های سریالایز شده) باید از FileManager با پوشه Documents یا CoreData استفاده کنید. علاوه بر این، UserDefaults از نسخه‌گذاری طرح داده پشتیبانی نمی‌کند — هنگام تغییر ساختار مدل Codable، داده‌های قدیمی ممکن است دیسریالایز نشوند و این باید در کد برنامه مدیریت شود.

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

تفاوت NSUserDefaults با SharedPreferences در Android چیست؟

هر دو فروشگاه کلید-مقدار هستند، اما NSUserDefaults انواع بیشتری (Data, Date, Array, Dictionary) را پشتیبانی می‌کند و به طور خودکار با iCloud همگام می‌شود. SharedPreferences داده‌ها را در XML ذخیره می‌کند، NSUserDefaults — در قالب plist. NSUserDefaults دارای سیستم دامنه با جستجوی آبشاری است، SharedPreferences از ساختار تخت ساده با نام فایل‌ها استفاده می‌کند.

آیا ذخیره رمزهای عبور در NSUserDefaults امن است؟

خیر، NSUserDefaults داده‌ها را به صورت آشکار بدون رمزگذاری ذخیره می‌کند. برای رمزهای عبور، توکن‌ها و کلیدهای رمزگذاری از Keychain استفاده کنید که داده‌ها را در سطح Secure Enclave رمزگذاری می‌کند. Keychain همچنین از ویژگی‌های دسترسی مانند احراز هویت بیومتریک (Face ID / Touch ID) قبل از خواندن رمز پشتیبانی می‌کند.

چگونه NSUserDefaults را بین دستگاه‌ها همگام‌سازی کنیم؟

برای همگام‌سازی بین دستگاه‌های یک کاربر از NSUbiquitousKeyValueStore — فروشگاه کلید-مقدار ابری iCloud استفاده کنید. داده‌های نوشته شده در این سرویس در یک دستگاه به طور خودکار در همه دستگاه‌های دیگر همان حساب iCloud ظاهر می‌شوند. حداکثر حجم — 1 MB برای هر برنامه، 1024 کلید.

چگونه تمام داده‌ها را از NSUserDefaults حذف کنیم؟

برای حذف همه داده‌ها، متد removePersistentDomain(forName:) را با Bundle Identifier برنامه فراخوانی کنید. برای حذف مقادیر تکی از removeObject(forKey:) استفاده کنید. برای بازنشانی کامل تنظیمات برنامه: UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!). همه حذف‌ها فوراً در کش حافظه اعمال می‌شوند.

حداکثر اندازه داده در NSUserDefaults چقدر است؟

Apple محدودیت سختی برای اندازه NSUserDefaults تعیین نمی‌کند، اما توصیه می‌شود از 100 KB برای حجم کل تمام داده‌های ذخیره شده تجاوز نکنید. برای حجم‌های بزرگ از CoreData یا FileManager استفاده کنید. هنگام ذخیره بیش از 1 MB داده، عملکرد خواندن در راه‌اندازی برنامه می‌تواند به طور محسوسی کاهش یابد.

خلاصه

  • NSUserDefaults — فروشگاه داخلی کلید-مقدار Apple برای تنظیمات ساده برنامه در قالب plist.
  • از نه نوع داده پشتیبانی می‌کند: String، Int، Bool، Float، Double، Data، Date، Array و Dictionary.
  • از سیستم دامنه با جستجوی آبشاری از طریق NSRegistrationDomain، NSGlobalDomain و دامنه برنامه استفاده می‌کند.
  • برای همگام‌سازی بین دستگاه‌ها، Apple NSUbiquitousKeyValueStore را با محدودیت 1 MB برای هر برنامه ارائه می‌دهد.
  • برای امنیت از Keychain برای رمزهای عبور و توکن‌ها استفاده کنید، نه NSUserDefaults.
  • در SwiftUI روش ترجیحی کار — Property Wrapper @AppStorage با همگام‌سازی خودکار UI است.
  • برای داده‌های بزرگ یا ساختاریافته CoreData یا FileManager را به جای NSUserDefaults انتخاب کنید.

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

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

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

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