用來做簡單數據存儲的Preference
在我們的日常開發中使用的還是比較多的,但使用起來總感覺不那么方便。比如說需要去手動管理key
,之前是這樣做的。
public enum UserDefaultsKey: String { case keyOne case keyTwo } extension UserDefaults { /// 存儲 public final class func set(_ value: Any, forKey: UserDefaultsKey) { UserDefaults.standard.set(value, forKey: forKey.rawValue) } /// 讀取 public final class func getString(forKey: UserDefaultsKey) -> String? { return UserDefaults.standard.string(forKey: forKey.rawValue) } public final class func getBool(forKey: UserDefaultsKey) -> Bool? { return UserDefaults.standard.bool(forKey: forKey.rawValue) } } // 存儲數據 UserDefaults.set(true, forKey: .keyOne) // 讀取數據 UserDefaults.getBool(forKey: .keyOne)
或者是這樣做的
var AuthToken:String?{ set{ let userData:UserDefaults=UserDefaults.standard userData.set(newValue, forKey: "AccountInfo_AuthToken") } get{ let userData:UserDefaults=UserDefaults.standard return userData.object(forKey: "AccountInfo_AuthToken") as? String } }
我們可以通過使用 #function
避免手動管理key
,在存儲和讀取數據時調動的set
和get
方法也可以交給目標屬性默認的set
和get
方法去做。
extension UserDefaults { /// 通過下標使用枚舉 subscript<T: RawRepresentable>(key: String) -> T? { get { if let rawValue = value(forKey: key) as? T.RawValue { return T(rawValue: rawValue) } return nil } set { set(newValue?.rawValue, forKey: key) } } subscript<T>(key: String) -> T? { get { return value(forKey: key) as? T } set { set(newValue, forKey: key) } } } struct Preference { /// bool static var isFirstLogin: Bool { get { return UserDefaults.standard[#function] ?? false } set { UserDefaults.standard[#function] = newValue } } /// string static var userName: String { get { return UserDefaults.standard[#function] ?? "yourDefaultValue" } set { UserDefaults.standard[#function] = newValue } } /// enum static var appTheme: Theme { get { return UserDefaults.standard[#function] ?? .light } set { UserDefaults.standard[#function] = newValue } } /// 測試服跟正式服之間的切換(默認正式服) static var serverUrl: ServerUrlType { get { return UserDefaults.standard[#function] ?? .distributeServer } set { UserDefaults.standard[#function] = newValue } } } enum Theme: Int { case light case dark case blue } enum ServerUrlType: String { case developServer = "url: developServer" // 測試服 case distributeServer = "url: distributeServer" // 正式服 } // 存儲數據 Preference.isFirstLogin = true Preference.appTheme = .dark Preference.serverUrl = .developServer // 讀取數據 Preference.isFirstLogin // true Preference.appTheme == .dark // true Preference.serverUrl.rawValue // url: developServer
在測試環節經常需要在測試服和正式服來回切換,為了避免老是打包,我們可以利用UserDefaults
去更改服務器地址,在適當的位置(可以是個測試頁面)加個UISwitch
,然后設置serverUrl
的值。
UserDefaults
有性能問題嗎?UserDefaults
是帶緩存的。它會把訪問到的key
緩存到內存中,下次再訪問時,如果內存中命中就直接訪問,如果未命中再從文件中載入。它還會時不時調用同步方法來保證內存與文件中的數據的一致性,有時在寫入一個值后也最好調用下這個方法來保證數據真正寫入文件。