iOS UserDefaults
UserDefaults 是 iOS 開發中最常見的資料持久化方式,適合用來儲存少量的使用者設定(例如:音量大小、是否開啟通知、使用者暱稱、最後一次登入時間等)。
它是一個 Key-Value (鍵值對) 儲存系統,用法類似於字典 (Dictionary)。資料會被儲存在各個 App 的 sandboxed file system 中的 .plist 檔案裡。
什麼不適合存?
- 大量資料:如大圖片或數千筆記錄,請使用
FileManager,CoreData或SwiftData。 - 敏感資料:如使用者密碼、Token,請務必使用 Keychain,因 UserDefaults 的資料是未加密的純文字。
基本用法
Swift 提供了一個單例 (Singleton) UserDefaults.standard 來讓我們存取預設的儲存區。
儲存資料 (Set)
使用 set(_:forKey:) 方法。
// 儲存整數
UserDefaults.standard.set(25, forKey: "TextSize")
// 儲存布林值
UserDefaults.standard.set(true, forKey: "IsDarkMode")
// 儲存字串
UserDefaults.standard.set("Mike", forKey: "UserName")
// 儲存日期
UserDefaults.standard.set(Date(), forKey: "LastLogin")
讀取資料 (Get)
UserDefaults 針對不同型別提供了對應的讀取方法。注意部份方法有預設行為:
// 讀取整數 (若 key 不存在則回傳 0)
let size = UserDefaults.standard.integer(forKey: "TextSize")
// 讀取布林值 (若 key 不存在則回傳 false)
let isDarkMode = UserDefaults.standard.bool(forKey: "IsDarkMode")
// 讀取字串 (回傳 String?,可能為 nil)
let name = UserDefaults.standard.string(forKey: "UserName")
// 讀取日期 (回傳 Any?,需轉型)
let loginDate = UserDefaults.standard.object(forKey: "LastLogin") as? Date
移除資料 (Remove)
UserDefaults.standard.removeObject(forKey: "UserName")
支援的資料型別
UserDefaults 原生僅支援以下型別 (PropertyList 兼容型別):
DataStringNumber(Int, Float, Double, Bool)DateArray(成員必須也是支援的型別)Dictionary(成員必須也是支援的型別)
儲存自定義物件 (Custom Objects)
如果你想儲存一個自定義的 Struct (例如 User),直接塞給 UserDefaults 會 Crash。
正確做法是:
- 讓 Struct 遵循
Codable協議。 - 使用
JSONEncoder編碼成Data存入。 - 讀取時使用
JSONDecoder解碼。
struct UserProfile: Codable {
var name: String
var age: Int
}
let user = UserProfile(name: "Alice", age: 30)
// --- 儲存 ---
if let encoded = try? JSONEncoder().encode(user) {
UserDefaults.standard.set(encoded, forKey: "CurrentUser")
}
// --- 讀取 ---
if let savedData = UserDefaults.standard.data(forKey: "CurrentUser"),
let loadedUser = try? JSONDecoder().decode(UserProfile.self, from: savedData) {
print("User: \(loadedUser.name), Age: \(loadedUser.age)")
}
SwiftUI 的 @AppStorage
在 SwiftUI 中,我們很少直接寫 UserDefaults.standard.set。取而代之的是使用 @AppStorage 這個 Property Wrapper。
它會自動將變數與 UserDefaults 綁定,當數值改變時,會自動寫入,並且自動更新 View。
import SwiftUI
struct SettingsView: View {
// 當你在 UI 修改 isDarkMode,UserDefaults 裡的 "isDarkMode" key 也會跟著變
// 若 UserDefaults 裡沒值,則使用 false 為預設值
@AppStorage("isDarkMode") private var isDarkMode = false
@AppStorage("username") private var username = "Guest"
var body: some View {
Form {
Toggle("暗黑模式", isOn: $isDarkMode)
TextField("暱稱", text: $username)
}
}
}
@AppStorage 目前僅支援基本的型別 (String, Int, Double, Bool, URL, Data),不支援直接存取 Struct/Class。若要存複雜物件,仍建議封裝一層 ViewModel 使用上述 Codable 的方法。