如何在 Swift 中实现一个管理 UserDefaults 的键值对的通用结构?
Posted
技术标签:
【中文标题】如何在 Swift 中实现一个管理 UserDefaults 的键值对的通用结构?【英文标题】:How can I implement a generic struct that manages key-value pairs for UserDefaults in Swift? 【发布时间】:2021-02-09 21:22:15 【问题描述】:如何在 Swift 中实现一个管理 UserDefaults 映射的结构? 现在我有一些不同类型的计算属性 a、b、c、d 和对应的键,如下所示:
enum UserDefaultsKeys
a_key
b_key
...
var a: String
get UserDefaults.standard.string(forKey: UserDefaultsKeys.a_key.rawValue)
set UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.a_key.rawValue)
var b: Int
get UserDefaults.standard.integer(forKey: UserDefaultsKeys.b_key.rawValue)
set UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.b_key.rawValue)
...
我想要实现的是实现一个结构,该结构具有字符串类型的键和泛型类型值。
值获取函数应该 - 根据它的类型 - 选择使用 UserDefaults.standard.string
或 UserDefaults.standard.integer
以便我可以使用一些键创建一个 DefaultsVar,而其他所有内容都会为我自动管理。
我到目前为止是这样的:
struct DefaultsVar<T>
let key: String
var value: T
get
switch self
case is String: return UserDefaults.standard.string(forKey: key) as! T
case is Int: return UserDefaults.standard.integer(forKey: key) as! T
default: return UserDefaults.standard.float(forKey: key) as! T
set UserDefaults.standard.set(newValue, forKey: key)
我收到以下错误:“从 DefaultsVar 转换为不相关的类型 'String' 总是失败。 我对 swift 完全陌生(对编程也相对较新)并且并不真正了解如何以正确的方式实现这一点 - 或者这甚至是一种被认为是一种好的做法。有人可以对此有所了解吗?
提前谢谢你!
【问题讨论】:
有什么好处?UserDefaults
的 setter 是 已经是通用的,只有少数支持的类型。
我认为它可能会阻止所有变量的一些样板代码。
【参考方案1】:
您可以使用自定义
属性包装器:
@propertyWrapper
struct UserDefaultStorage<T: Codable>
private let key: String
private let defaultValue: T
private let userDefaults: UserDefaults
init(key: String, default: T, store: UserDefaults = .standard)
self.key = key
self.defaultValue = `default`
self.userDefaults = store
var wrappedValue: T
get
guard let data = userDefaults.data(forKey: key) else
return defaultValue
let value = try? JSONDecoder().decode(T.self, from: data)
return value ?? defaultValue
set
let data = try? JSONEncoder().encode(newValue)
userDefaults.set(data, forKey: key)
此包装器可以将任何类型的可编码存储/恢复到用户默认值中/从用户默认值中恢复。
用法
@UserDefaultStorage(key: "myCustomKey", default: 0)
var myValue: Int
ios 14
SwiftUI 有一个类似的包装器(仅适用于 iOS 14),称为 @AppStorage
,它可以用作状态。使用这个的好处是可以直接作为State
使用。但它需要SwiftUI
,并且只能在 iOS 14 上使用。
【讨论】:
无需从Any
转换为Data
。 UserDefaults
有一个特定的方法来准确地从中检索数据。 data(forKey:)
.
是的,你是对的@LeoDabus。我应该更新我的要点 :) 谢谢
太棒了!谢谢您的回答!但是有一个问题:如果没有值可以返回,返回一个默认值(从而隐藏可能发生的错误)而不是抛出一个错误真的更可取吗?
类本身总是返回一个默认值。顺便说一句,我们说的是用户 Defaults 对吗? ;)
不客气。如果它对您有帮助,请不要忘记 upvote,如果它是您的答案,请不要忘记 接受 ;)以上是关于如何在 Swift 中实现一个管理 UserDefaults 的键值对的通用结构?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 inputAccessoryView [Swift] 中实现滚动视图
如何使用 Swift 在 CustomCell 中实现 inputAccessoryView 到 UITextField?