NSUserDefaults adalah penyimpanan data kunci-nilai di iOS, watchOS, tvOS dan macOS, yang dirancang untuk menyimpan pengaturan dan konfigurasi aplikasi. Data disimpan dalam file plist di sandbox aplikasi dan secara otomatis disinkronkan dengan iCloud melalui NSUbiquitousKeyValueStore. Menurut dokumentasi resmi Apple Developer, 2025, NSUserDefaults mendukung penyimpanan tipe primitif: String, Int, Bool, Float, Double, Data, Date, Array dan Dictionary. Kelas ini telah diganti nama menjadi UserDefaults sejak Swift 3, tetapi nama Objective-C NSUserDefaults tetap banyak digunakan dalam basis kode dan dokumentasi Apple.
Poin Utama
NSUserDefaults (UserDefaults di Swift) adalah mekanisme bawaan Apple untuk menyimpan pasangan kunci-nilai dalam format plist. Ini tersedia di semua platform Apple: iOS, iPadOS, watchOS, tvOS dan macOS. Tujuan utama — menyimpan preferensi pengguna, status antarmuka, flag first-launch, opsi yang dipilih dan data sederhana lainnya yang bertahan setelah restart aplikasi.
Setiap aplikasi iOS memiliki sandbox terisolasi, dan NSUserDefaults disimpan di direktori Library/Preferences di dalam sandbox ini dalam file bernama Bundle Identifier. File plist berisi pasangan kunci-nilai, di mana kuncinya adalah string dan nilainya adalah salah satu tipe yang didukung. Ukuran file tidak dibatasi, tetapi Apple merekomendasikan untuk hanya menyimpan pengaturan di UserDefaults, bukan data dalam jumlah besar.
Sejak iOS 8, NSUserDefaults mendukung App Groups — penyimpanan bersama antara aplikasi dari pengembang yang sama dan ekstensi mereka (widget, aplikasi pendamping watchOS). Untuk ini digunakan inisialisator init?(suiteName:) dengan pengenal App Group. Ini memungkinkan, misalnya, widget di layar Today untuk membaca pengaturan dari aplikasi utama tanpa menduplikasi logika penyimpanan.
Secara fisik, NSUserDefaults disimpan dalam file plist biner di jalur: {Sandbox}/Library/Preferences/com.example.myapp.plist. File menggunakan format plist biner (NSPropertyListBinaryFormat_v1_0) untuk kekompakan dan kecepatan baca. Di macOS, file bisa dalam format XML untuk kompatibilitas. Berbeda dengan SharedPreferences di Android, file plist UserDefaults dapat berisi struktur bersarang melalui Dictionary dan Array.
File NSUserDefaults tidak dienkripsi secara default. Data disimpan dalam bentuk terbuka dan dapat dibaca dengan akses fisik ke perangkat atau melalui cadangan. Untuk menyimpan data sensitif (kata sandi, token, kunci enkripsi), Apple dengan tegas merekomendasikan penggunaan Keychain, yang secara otomatis mengenkripsi data di tingkat sistem operasi.
NSUserDefaults bekerja berdasarkan prinsip caching di memori dengan sinkronisasi periodik ke disk. Pada akses pertama ke instance standar UserDefaults.standard, sistem memuat file plist ke dalam RAM dalam bentuk Dictionary. Semua pembacaan berikutnya dilakukan dari memori. Penulisan juga pertama dilakukan di memori, dan sinkronisasi ke disk terjadi secara periodik di latar belakang.
Operasi penulisan menggunakan metode set(_:forKey:), yang menerima nilai opsional dari tipe Any?. Nilai bisa nil — untuk menghapus kunci. Untuk penulisan segera ke disk, sebelumnya digunakan metode synchronize(), tetapi sejak iOS 7 dan OS X 10.9 tidak lagi diperlukan — sistem secara otomatis menyinkronkan data secara berkala. Apple secara resmi telah menyatakan synchronize() berlebihan dalam dokumentasinya.
NSUserDefaults menggunakan sistem register (domain) untuk mengatur pencarian nilai. Ketika aplikasi meminta nilai berdasarkan kunci, UserDefaults secara berurutan memeriksa domain dalam urutan tertentu: pertama NSArgumentDomain (argumen baris perintah), kemudian domain aplikasi (Application), kemudian NSGlobalDomain (pengaturan sistem), kemudian domain spesifik bahasa dan terakhir NSRegistrationDomain (nilai default yang didaftarkan melalui register(defaults:)).
import Foundation
// Instance standar UserDefaults
let defaults = UserDefaults.standard
// Menulis nilai
defaults.set("Anna Petrova", forKey: "username")
defaults.set(28, forKey: "age")
defaults.set(true, forKey: "isLoggedIn")
// Pendaftaran nilai default
defaults.register(defaults: [
"theme": "system",
"fontSize": 14
])
// Membaca dengan mengembalikan nilai default
let theme = defaults.string(forKey: "theme") ?? "system"
let fontSize = defaults.integer(forKey: "fontSize")
Domain NSRegistrationDomain adalah domain perangkat lunak yang hanya ada di RAM dan tidak disimpan ke disk. Ini digunakan untuk menetapkan nilai default yang berlaku sampai aplikasi menulis nilainya sendiri ke domain aplikasi. Ini memungkinkan pembuatan titik konfigurasi tunggal untuk pengaturan default yang dapat diubah secara terpusat pada tahap pengembangan.
NSUserDefaults menyediakan serangkaian metode yang diketik untuk membaca dan menulis data: string(forKey:), integer(forKey:), bool(forKey:), float(forKey:), double(forKey:), data(forKey:), array(forKey:), dictionary(forKey:) dan object(forKey:). Setiap metode baca memiliki metode tulis yang sesuai set(_:forKey:) dengan penentuan otomatis tipe nilai yang disimpan. Versi Swift dari UserDefaults menggunakan pengetikan ketat, tetapi versi Objective-C menerima dan mengembalikan id.
| Metode baca (Swift) | Tipe data | Nilai default |
|---|---|---|
| string(forKey:) | String? | nil |
| integer(forKey:) | Int | 0 |
| bool(forKey:) | Bool | false |
| float(forKey:) | Float | 0.0 |
| double(forKey:) | Double | 0.0 |
| data(forKey:) | Data? | nil |
Metode synchronize() di NSUserDefaults memaksa penulisan semua perubahan dari memori ke disk. Di versi awal iOS, metode ini harus dipanggil setelah setiap penulisan untuk menjamin penyimpanan data. Sejak iOS 7, sistem secara otomatis menyinkronkan UserDefaults di latar belakang, dan Apple secara resmi telah menyatakan synchronize() berlebihan. Pemanggilan metode ini tidak menyebabkan kesalahan, tetapi tidak memberikan jaminan penyimpanan tambahan.
Untuk memantau perubahan, NSUserDefaults menyediakan notifikasi UserDefaults.didChangeNotification dan metode observasi KVO addObserver(_:forKeyPath:options:context:). Di SwiftUI, tersedia Property Wrapper @AppStorage, yang secara otomatis menyinkronkan nilai di UserDefaults dengan pembaruan UI. @AppStorage mendukung tipe yang sama dengan UserDefaults dan merupakan cara yang lebih disukai untuk bekerja dengan pengaturan di aplikasi SwiftUI.
// Mengamati perubahan melalui KVO
class SettingsViewModel: NSObject {
override func observeValue(
forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey: Any]?,
context: UnsafeMutableRawPointer?
) {
guard let keyPath else { return }
print("Kunci berubah: \(keyPath)")
}
}
// SwiftUI - AppStorage
struct SettingsView: View {
@AppStorage("theme") private var theme: String = "system"
var body: some View {
Picker("Tema", selection: $theme) {
Text("Sistem").tag("system")
Text("Terang").tag("light")
Text("Gelap").tag("dark")
}
}
}
Untuk bekerja dengan App Groups (penyimpanan bersama antara aplikasi dan ekstensi) digunakan inisialisator UserDefaults(suiteName:) dengan pengenal App Group. Misalnya, "group.com.example.myapp". Data yang ditulis ke instance ini dapat diakses dari aplikasi utama, widget, aplikasi pendamping watchOS dan ekstensi lain yang termasuk dalam App Group yang sama. Setiap instance suite disimpan dalam file plist terpisah.
Meskipun nyaman dan sederhana, NSUserDefaults bukanlah penyimpanan universal untuk semua tipe data di iOS. Tergantung pada volume, kepentingan dan persyaratan keamanan, Apple menyediakan beberapa alternatif, masing-masing dioptimalkan untuk skenario penggunaan tertentu.
| Solusi | Kapan digunakan | Keterbatasan |
|---|---|---|
| NSUserDefaults | Pengaturan antarmuka dan konfigurasi | Tidak cocok untuk data besar dan rahasia |
| Keychain | Kata sandi, token, kunci enkripsi | Lebih rumit digunakan, lebih lambat |
| CoreData | Data terstruktur dengan relasi | Berlebihan untuk 10-20 pengaturan |
| FileManager | Dokumen, gambar, data biner | Memerlukan manajemen file manual |
| CloudKit | Sinkronisasi cloud antar perangkat | Memerlukan akun iCloud dan koneksi jaringan |
Keychain adalah penyimpanan terlindungi Apple untuk data rahasia. Berbeda dengan NSUserDefaults, semua data di Keychain dienkripsi di tingkat sistem operasi menggunakan enkripsi perangkat keras Secure Enclave pada perangkat yang kompatibel. Keychain secara otomatis terkunci dan terbuka bersama perangkat dan mendukung pembagian akses antar aplikasi dari pengembang yang sama melalui Keychain Access Groups.
Kekurangan utama Keychain adalah kompleksitas API. Untuk menyimpan string sederhana, perlu membuat permintaan SecItemAdd dengan menentukan atribut: kelas (kSecClassGenericPassword), layanan (kSecAttrService), akun (kSecAttrAccount) dan data itu sendiri (kSecValueData). Untuk menyederhanakan pekerjaan dengan Keychain, ada pembungkus pihak ketiga seperti KeychainAccess dan SwiftKeychainWrapper, yang menyediakan antarmuka kunci-nilai yang nyaman mirip dengan UserDefaults.
Mari kita lihat contoh praktis: menyimpan dan memulihkan status onboarding (layar selamat datang) di aplikasi iOS menggunakan NSUserDefaults. Pada peluncuran pertama, pengguna melihat layar onboarding, setelah melewatinya sebuah flag disimpan di UserDefaults. Pada peluncuran berikutnya, onboarding dilewati. Untuk SwiftUI digunakan @AppStorage, untuk UIKit — akses langsung ke UserDefaults.standard.
Mari buat manajer OnboardingManager yang merangkum pekerjaan dengan UserDefaults untuk menyimpan status onboarding. Manajer menyediakan properti isOnboardingCompleted untuk memeriksa status dan metode markOnboardingCompleted untuk mengatur flag. Kunci penyimpanan ditempatkan di konstanta untuk mencegah kesalahan ketik. Untuk pengujian unit, manajer menggunakan protokol UserDefaultsProtocol, yang memungkinkan penggantian penyimpanan nyata dengan MockUserDefaults.
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)
}
}
// Penggunaan dalam aplikasi
let onboardingManager = OnboardingManager()
if !onboardingManager.isOnboardingCompleted {
showOnboarding()
} else {
showMainScreen()
}
Untuk menyimpan pengaturan yang lebih kompleks, seperti objek Profile terstruktur, disarankan menggunakan protokol Codable dan JSONEncoder/JSONDecoder. Objek diserialisasi ke Data melalui JSONEncoder, disimpan melalui set(_:forKey:), dan saat dibaca dideserialisasi dari Data kembali ke objek melalui JSONDecoder. Pendekatan ini memungkinkan penyimpanan struktur kompleks di UserDefaults tanpa kehilangan keamanan tipe.
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)
}
}
// Penggunaan
let profile = UserProfile(name: "Anna", age: 28, preferences: ["theme": "dark"])
UserDefaults.standard.save(profile, forKey: "user_profile")
let loaded = UserDefaults.standard.load(UserProfile.self, forKey: "user_profile")
Penting untuk diingat bahwa NSUserDefaults tidak dirancang untuk menyimpan data dalam jumlah besar. Apple merekomendasikan untuk membatasi ukuran data yang disimpan hingga beberapa puluh kilobyte. Untuk menyimpan objek besar (gambar, dokumen, model terserialisasi) harus menggunakan FileManager dengan direktori Documents atau CoreData. Selain itu, UserDefaults tidak mendukung versioning skema data — ketika struktur model Codable berubah, data lama mungkin tidak dapat dideserialisasi dan ini perlu ditangani dalam kode aplikasi.
Pertanyaan yang Sering Diajukan
Keduanya adalah penyimpanan kunci-nilai, tetapi NSUserDefaults mendukung lebih banyak tipe (Data, Date, Array, Dictionary) dan secara otomatis sinkron dengan iCloud. SharedPreferences menyimpan data di XML, NSUserDefaults — dalam format plist. NSUserDefaults memiliki sistem domain dengan pencarian kaskade, SharedPreferences menggunakan struktur datar sederhana dengan nama file.
Tidak, NSUserDefaults menyimpan data dalam bentuk terbuka tanpa enkripsi. Untuk kata sandi, token dan kunci enkripsi, gunakan Keychain yang mengenkripsi data di tingkat Secure Enclave. Keychain juga mendukung atribut akses seperti autentikasi biometrik (Face ID / Touch ID) sebelum membaca rahasia.
Untuk sinkronisasi antar perangkat pengguna yang sama, gunakan NSUbiquitousKeyValueStore — penyimpanan kunci-nilai cloud iCloud. Data yang ditulis ke layanan ini di satu perangkat secara otomatis muncul di semua perangkat lain dengan akun iCloud yang sama. Volume maksimum — 1 MB per aplikasi, 1024 kunci.
Untuk menghapus semua data, panggil metode removePersistentDomain(forName:) dengan Bundle Identifier aplikasi. Untuk menghapus nilai individual, gunakan removeObject(forKey:). Untuk reset penuh pengaturan aplikasi: UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!). Semua penghapusan segera diterapkan ke cache memori.
Apple tidak menetapkan batasan ketat untuk ukuran NSUserDefaults, tetapi disarankan untuk tidak melebihi 100 KB untuk total volume semua data yang disimpan. Untuk volume besar, gunakan CoreData atau FileManager. Saat menyimpan lebih dari 1 MB data, kinerja pembacaan saat memulai aplikasi dapat menurun secara signifikan.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga