我有一些通用代码,允许我在默认系统中读取和写入各种类型,例如,值getter和setter:
var value : T {
get {
if T.self == Int.self {
return UserDefaults.standard.integer(forKey: storageKey) as! T
} else if T.self == Double.self {
return UserDefaults.standard.double(forKey: storageKey) as! T
} else if T.self == Float.self {
return UserDefaults.standard.float(forKey: storageKey) as! T
} else if T.self == Bool.self {
return UserDefaults.standard.bool(forKey: storageKey) as! T
} else if T.self == String.self {
return UserDefaults.standard.string(forKey: storageKey) as! T
} else {
return UserDefaults.standard.value(forKey: self.storageKey) as! T
}
}
set(value) {
UserDefaults.standard.set(value, forKey: storageKey)
UserDefaults.standard.synchronize()
}
}现在我想将我自己的枚举类型添加到这个机制中,方法是将它们设置为RawRepresentable<Int>,例如
enum Direction : Int, RawRepresentable {
case left = 0
case right = 1
}不幸的是,我既找不到测试T是否符合RawRepresentable协议的魔术咒语,也不能将T转换为RawRepresentable协议,因为无论我做什么尝试,最终都会得到一个Protocol 'RawRepresentable' can only be used as a generic constraint because it has Self or associated type requirements。
我已经尝试了每一个where和as咒语,直到我开始怀疑它是否能做到!?
我在Swift 5中,目标是通过调用CustomType(rawValue:)来创建新实例,并通过调用myValue.rawValue来获取Int值。
发布于 2020-06-20 19:04:49
正如@vadian所说,所有这些类型检查都可以被替换为对UserDefaults.standard.object()和条件强制转换的单个调用。此外,value属性的类型需要是可选的,以处理属性未设置(或类型不正确)的情况:
struct DefaultKey<T> {
let storageKey: String
var value: T? {
get {
return UserDefaults.standard.object(forKey: storageKey) as? T
}
nonmutating set {
UserDefaults.standard.set(newValue, forKey: storageKey)
}
}
}然后,您可以定义一个受约束的扩展方法,在此方法中,您可以为RawRepresentable类型专门化computed属性:
extension DefaultKey where T: RawRepresentable {
var value: T? {
get {
if let rawValue = UserDefaults.standard.object(forKey: storageKey) as? T.RawValue {
return T(rawValue: rawValue)
}
return nil
}
nonmutating set {
UserDefaults.standard.set(newValue?.rawValue, forKey: storageKey)
}
}
}示例用法:
enum Direction : Int {
case left = 0
case right = 1
}
let key1 = DefaultKey<Int>(storageKey: "foo")
key1.value = 123
let key2 = DefaultKey<Direction>(storageKey: "bar")
key2.value = .right
print(key1.value as Any) // Optional(123)
print(key2.value as Any) // Optional(Direction.right)请注意,如果与非属性列表类型一起使用,这仍然可能会崩溃。为了安全起见,您必须将扩展限制为已知为用户默认可存储的类型(整数、浮点数、字符串等):
protocol UserDefaultsStorable {}
extension Int: UserDefaultsStorable {}
extension Float: UserDefaultsStorable {}
// ...
struct DefaultKey<T> {
let storageKey: String
}
extension DefaultKey where T: UserDefaultsStorable { .. }
extension DefaultKey where T: RawRepresentable, T.RawValue: UserDefaultsStorable { ... }https://stackoverflow.com/questions/62483918
复制相似问题