如何在 propertyWrapped UserDefault 中集成枚举
How to integrate enums in propertyWrapped UserDefault
下面的结构适用于 Int
、String
、Double
等原始数据类型,有没有办法使它适用于枚举,以便我不必使用 rawValues 进行手动解析?
@propertyWrapper
struct Storage<T> {
let objectName: String
let defaultValue: T
let defaults: UserDefaults
init(_ objectName: String, defaultValue: T, defaults: UserDefaults = .standard) {
self.objectName = objectName
self.defaultValue = defaultValue
self.defaults = defaults
}
var wrappedValue: T {
get { return self.defaults.object(forKey: self.objectName) as? T ?? self.defaultValue }
set { self.defaults.set(newValue, forKey: self.objectName) }
}
}
目前我的解决方法是将对象包装在另一个 getter 和 setter 中作为枚举。
enum SomeType: String {
case foo, bar, baz
}
class Defaults {
@Storage("object", default: "")
private var: objectContainer: String
var object: SomeType? {
get {
return SomeType(rawValue: self.objectContainer)
}
set {
self.objectContainer = newValue.rawValue ?? ""
}
}
}
我试图为 RawRepresentable
类型创建一个不同的 属性 包装器,但是 Swift 无法从中推断出 T
的类型。
@propertyWrapper
struct RawRepresentableStorage<T: RawRepresentable> {
let objectName: String
let defaultValue: T
let defaults: UserDefaults
init(_ objectName: String, defaultValue: T, defaults: UserDefaults = .standard) {
self.objectName = objectName
self.defaultValue = defaultValue
self.defaults = defaults
}
var wrappedValue: T {
get {
guard let object = self.defaults.object(forKey: self.objectName) as? T else {
return self.defaultValue
}
// Error on this line:
// `Cannot convert value of type 'T' to expected argument type 'T.RawValue'`
return T(rawValue: object) ?? self.defaultValue
}
set {
self.defaults.set(newValue.rawValue, forKey: self.objectName)
}
}
}
为代码库中的每个可存储枚举创建包装器类型也不是理想的选择,即使它们只有少数几个
我是否遗漏了什么,或者这是 Swift 的当前限制?
在您的 wrappedValue
getter 中,您正在转换为错误的类型。您正在将 object
传递给 T(rawValue:)
,因此它的类型需要是 T.RawValue
,而不是 T
。
@propertyWrapper
struct RawRepresentableStorage<T: RawRepresentable> {
let objectName: String
let defaultValue: T
let defaults: UserDefaults
init(_ objectName: String, defaultValue: T, defaults: UserDefaults = .standard) {
self.objectName = objectName
self.defaultValue = defaultValue
self.defaults = defaults
}
var wrappedValue: T {
get {
guard let object = self.defaults.object(forKey: self.objectName) as? T.RawValue else {
return self.defaultValue
}
return T(rawValue: object) ?? self.defaultValue
}
set {
self.defaults.set(newValue.rawValue, forKey: self.objectName)
}
}
}
下面的结构适用于 Int
、String
、Double
等原始数据类型,有没有办法使它适用于枚举,以便我不必使用 rawValues 进行手动解析?
@propertyWrapper
struct Storage<T> {
let objectName: String
let defaultValue: T
let defaults: UserDefaults
init(_ objectName: String, defaultValue: T, defaults: UserDefaults = .standard) {
self.objectName = objectName
self.defaultValue = defaultValue
self.defaults = defaults
}
var wrappedValue: T {
get { return self.defaults.object(forKey: self.objectName) as? T ?? self.defaultValue }
set { self.defaults.set(newValue, forKey: self.objectName) }
}
}
目前我的解决方法是将对象包装在另一个 getter 和 setter 中作为枚举。
enum SomeType: String {
case foo, bar, baz
}
class Defaults {
@Storage("object", default: "")
private var: objectContainer: String
var object: SomeType? {
get {
return SomeType(rawValue: self.objectContainer)
}
set {
self.objectContainer = newValue.rawValue ?? ""
}
}
}
我试图为 RawRepresentable
类型创建一个不同的 属性 包装器,但是 Swift 无法从中推断出 T
的类型。
@propertyWrapper
struct RawRepresentableStorage<T: RawRepresentable> {
let objectName: String
let defaultValue: T
let defaults: UserDefaults
init(_ objectName: String, defaultValue: T, defaults: UserDefaults = .standard) {
self.objectName = objectName
self.defaultValue = defaultValue
self.defaults = defaults
}
var wrappedValue: T {
get {
guard let object = self.defaults.object(forKey: self.objectName) as? T else {
return self.defaultValue
}
// Error on this line:
// `Cannot convert value of type 'T' to expected argument type 'T.RawValue'`
return T(rawValue: object) ?? self.defaultValue
}
set {
self.defaults.set(newValue.rawValue, forKey: self.objectName)
}
}
}
为代码库中的每个可存储枚举创建包装器类型也不是理想的选择,即使它们只有少数几个
我是否遗漏了什么,或者这是 Swift 的当前限制?
在您的 wrappedValue
getter 中,您正在转换为错误的类型。您正在将 object
传递给 T(rawValue:)
,因此它的类型需要是 T.RawValue
,而不是 T
。
@propertyWrapper
struct RawRepresentableStorage<T: RawRepresentable> {
let objectName: String
let defaultValue: T
let defaults: UserDefaults
init(_ objectName: String, defaultValue: T, defaults: UserDefaults = .standard) {
self.objectName = objectName
self.defaultValue = defaultValue
self.defaults = defaults
}
var wrappedValue: T {
get {
guard let object = self.defaults.object(forKey: self.objectName) as? T.RawValue else {
return self.defaultValue
}
return T(rawValue: object) ?? self.defaultValue
}
set {
self.defaults.set(newValue.rawValue, forKey: self.objectName)
}
}
}