Reading & Writing
What is UserDefaults?
UserDefaults is a simple key-value store for small amounts of user preferences. It persists data across app launches but is NOT encrypted.
Writing Values
let defaults = UserDefaults.standard
defaults.set("Alice", forKey: "username")
defaults.set(42, forKey: "launchCount")
defaults.set(true, forKey: "hasCompletedOnboarding")
defaults.set(Date(), forKey: "lastLoginDate")
Reading Values
let username = defaults.string(forKey: "username")
let launchCount = defaults.integer(forKey: "launchCount")
let hasOnboarded = defaults.bool(forKey: "hasCompletedOnboarding")
let lastLogin = defaults.object(forKey: "lastLoginDate") as? Date
Removing Values
defaults.removeObject(forKey: "username")
Register Defaults
Set default values for first launch:
defaults.register(defaults: [
"username": "Guest",
"launchCount": 0,
"hasCompletedOnboarding": false,
"theme": "system"
])
This does not write to disk until a value is explicitly set.
What to Store
Store only small, non-sensitive data:
- User preferences (theme, language)
- Feature flags
- Launch count
- Last run version
Do NOT store:
- Sensitive data (use Keychain)
- Large data (use file system)
- Complex objects (use Codable + FileManager)
Property Wrappers
@AppStorage for SwiftUI
@AppStorage provides a clean property wrapper for UserDefaults in SwiftUI:
struct SettingsView: View {
@AppStorage("theme") private var theme = "system"
@AppStorage("notificationsEnabled") private var notifications = true
@AppStorage("fontSize") private var fontSize = 16.0
var body: some View {
Form {
Picker("Theme", selection: $theme) {
Text("Light").tag("light")
Text("Dark").tag("dark")
Text("System").tag("system")
}
Toggle("Notifications", isOn: $notifications)
Slider(value: $fontSize, in: 12...24, step: 1)
}
}
}
@AppStorage vs @State
- @State: In-memory, lost when view recreates
- @AppStorage: Persists in UserDefaults, shared across the app
@AppStorage with Custom Defaults
Specify a custom UserDefaults suite:
@AppStorage("color", store: UserDefaults(suiteName: "com.app.group"))
private var color = "blue"
This is useful for App Groups where multiple extensions share data.
App Groups
Share UserDefaults between app and extensions:
let sharedDefaults = UserDefaults(suiteName: "group.com.app.shared")
sharedDefaults?.set("value", forKey: "key")
Combining with Observable
@Observable
class UserPreferences {
var theme: String {
get { UserDefaults.standard.string(forKey: "theme") ?? "system" }
set { UserDefaults.standard.set(newValue, forKey: "theme") }
}
var notificationsEnabled: Bool {
get { UserDefaults.standard.bool(forKey: "notificationsEnabled") }
set { UserDefaults.standard.set(newValue, forKey: "notificationsEnabled") }
}
}
Best Practices
Keep It Small
UserDefaults is not a database. Store only preferences and settings, not application data.
Thread Safety
UserDefaults is thread-safe for individual reads and writes. However, batch operations should be performed on a single thread.
Synchronize
defaults.synchronize()
This is rarely needed in modern iOS as UserDefaults auto-saves, but can be useful before app termination.
Testing
Use a custom suite for testing to avoid polluting shared defaults:
let testDefaults = UserDefaults(suiteName: "TestSuite")!
testDefaults.removePersistentDomain(forName: "TestSuite")
Migration
When changing default values, handle migrations:
func migrateDefaults() {
let version = defaults.integer(forKey: "dataVersion")
if version < 2 {
// Migrate from v1 to v2
defaults.set(2, forKey: "dataVersion")
}
}
Security
UserDefaults stores data in plaintext plist files. Never store sensitive information like passwords, tokens, or personal data. Use Keychain for that purpose.
Quiz
1. What is UserDefaults designed for?
2. What SwiftUI property wrapper binds to UserDefaults?
3. Should you store passwords in UserDefaults?
4. What does register(defaults:) do?
Flashcards
Question
What is UserDefaults?
Click to reveal answer
Answer
A simple key-value store for small user preferences. Stores plaintext plist files, not encrypted.
Question
How do you bind UserDefaults in SwiftUI?
Click to reveal answer
Answer
@AppStorage provides two-way property binding to UserDefaults values.
Question
When should you NOT use UserDefaults?
Click to reveal answer
Answer
For sensitive data (use Keychain), large data (use FileManager), or complex objects.
Question
What does register(defaults:) do?
Click to reveal answer
Answer
Sets fallback values that are returned before any value is explicitly written to UserDefaults.
Revision Notes
Key Takeaways
- 1. UserDefaults is for small, non-sensitive user preferences only
- 2. @AppStorage provides clean SwiftUI integration with UserDefaults
- 3. register(defaults:) sets fallback values before explicit writes
- 4. Never store sensitive data in UserDefaults - use Keychain instead
- 5. App Groups enable UserDefaults sharing between app and extensions
Interview Tips
- • Explain when to use UserDefaults vs Keychain vs Core Data
- • Know how @AppStorage simplifies SwiftUI UserDefaults binding
- • Discuss thread safety and synchronization of UserDefaults
- • Describe App Groups for shared UserDefaults between targets
Cheat Sheet
UserDefaults: Key-value store for small preferences. .set() and .string(forKey:) for read/write. @AppStorage for SwiftUI binding. register(defaults:) for fallback values. Not encrypted - use Keychain for sensitive data. Not a database - use SwiftData/CoreData for complex data.