- 原文地址:Let’s Simplify the Work with UserDefaults
- 原文作者:Nikita Ermolenko
- 译文出自:掘金翻译计划
- 本文永久链接:github.com/xitu/gold-m…
- 译者:talisk
- 校对者:allen,stormluke
每个人都用 UserDefaults 来存储一些简单的数据,并且知道使用该存储很容易。但是今天我会改善一点它的交互性!让我们从最明显的解决方案开始,并实现一些新颖且优雅的东西。😌
想象一下我们有一个服务 —— SettingsService。这个服务掌握了应用的设置 —— 正在使用哪个主题(黑暗,明亮),是否启用通知等等。为了实现它,大多数开发人员会首先考虑 UserDefaults。 当然,用哪种方式取决于具体情况,但先让我们来简化 UserDefaults。
- 我们的第一个最简方案
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 中,并使用依赖注入。
- 下一步,我想要摆脱 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)
}
}
}
看,怎么样!让我们继续:)
- 下标时间!我们刚刚把
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 呢?🤔
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
}
}
}
这里可以重构!
- 让我们为 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 世界的有趣新闻和文章!
希望你能喜欢我写的 extension!如果你有任何改进它的想法请告诉我!查看 UserDefaults 的最新版本 extension 尽情地体验一下吧:)
这就是在构建 ITC 时候的我
一个在 Rosberry 工作的毛发浓密的 iOS 工程师。热衷响应式编程,开源爱好者,循环引用检测人。:)
感谢 Evgeny Mikhaylov 和 Rosberry。
掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、前端、后端、区块链、产品、设计、人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。