[譯] 讓咱們來簡化 UserDefaults 的使用

每一個人都用 UserDefaults 來存儲一些簡單的數據,而且知道使用該存儲很容易。可是今天我會改善一點它的交互性!讓咱們從最明顯的解決方案開始,並實現一些新穎且優雅的東西。😌前端

想象一下咱們有一個服務 —— SettingsService。這個服務掌握了應用的設置 —— 正在使用哪一個主題(黑暗,明亮),是否啓用通知等等。爲了實現它,大多數開發人員會首先考慮 UserDefaults。 固然,用哪一種方式取決於具體狀況,但先讓咱們來簡化 UserDefaultsandroid

  1. 咱們的第一個最簡方案
class SettingsService {

    private enum Keys {
        static let isNotificationsEnabled = "isNotificationsEnabled"
    }

    var isNotificationsEnabled: Bool {
        get {
            let isEnabled = UserDefaults.standard.value(forKey: Keys.isNotificationsEnabled) as? Bool
            return isEnabled ?? true
        }
        set {
            UserDefaults.standard.setValue(newValue, forKey: Keys.isNotificationsEnabled)
        }
    }
}
複製代碼

爲了簡單化,我直接使用 UserDefaults.standard,但在一個真實項目中,你最好把它存到一個 property 中,並使用依賴注入。ios

  1. 下一步,我想要擺脫 Keys 枚舉——使用 #function 來代替:
class SettingsService {

    var isNotificationsEnabled: Bool {
        get {
            let isEnabled = UserDefaults.standard.value(forKey: #function) as? Bool
            return isEnabled ?? true
        }
        set {
            UserDefaults.standard.setValue(newValue, forKey: #function)
        }
    }
}
複製代碼

看,怎麼樣!讓咱們繼續:)git

  1. 下標時間!咱們剛剛把 value(forKey:) 方法封裝成支持範型的下標語法形式:
extension UserDefaults {

    subscript<T>(key: String) -> T? {
        get {
            return value(forKey: key) as? T
        }
        set {
            set(newValue, forKey: key)
        }
    }
}

class SettingsService {

    var isNotificationsEnabled: Bool {
        get {
            return UserDefaults.standard[#function] ?? true
        }
        set {
            UserDefaults.standard[#function] = newValue
        }
    }
}
複製代碼

它看起來已經很整潔了!可是 Enums 呢?🤔github

enum AppTheme: Int {
    case light
    case dark
}

class SettingsService {

    var appTheme: AppTheme {
        get {
            if let rawValue: AppTheme.RawValue = UserDefaults.standard[#function], let theme = AppTheme(rawValue: rawValue) {
                return theme
            }
            return .light
        }
        set {
            UserDefaults.standard[#function] = newValue.rawValue
        }
    }
}
複製代碼

這裏能夠重構!編程

  1. 讓咱們爲 RawRepresentable 值編寫一個相似的 subscript
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)
        }
    }
}

class SettingsService {
    
    var appTheme: AppTheme {
        get {
            return UserDefaults.standard[#function] ?? .light
        }
        set {
            UserDefaults.standard[#function] = newValue
        }
    }
}
複製代碼

立刻完成啦!請注意,此擴展僅適用於使用 RawRepresentable 的枚舉。後端


別忘了訂閱個人 telegram channel!第一時間瞭解 iOS 世界的有趣新聞和文章!bash


但願你能喜歡我寫的 extension!若是你有任何改進它的想法請告訴我!查看 UserDefaults最新版本 extension 盡情地體驗一下吧:)app

這就是在構建 ITC 時候的我post

一個在 Rosberry 工做的毛髮濃密的 iOS 工程師。熱衷響應式編程,開源愛好者,循環引用檢測人。:)

感謝 Evgeny MikhaylovRosberry


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索