Swift 测试是否符合可代表性协议,以及是否符合可代表性协议

Swift 测试是否符合可代表性协议,以及是否符合可代表性协议,swift,generics,protocols,Swift,Generics,Protocols,我有一些通用代码,允许我读写各种类型的默认系统,例如值获取程序和设置程序: 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.

我有一些通用代码,允许我读写各种类型的默认系统,例如值获取程序和设置程序:

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()
    }
}
现在,我想通过使自己的枚举类型
rawrrepresentable
,将它们添加到此机制中,例如

enum Direction : Int, RawRepresentable {
    case left = 0
    case right = 1
}
不幸的是,我既找不到魔法咒语来测试
T
是否符合
rawrrepresentable
协议,也无法将
T
施法到
rawrrepresentable
协议,因为无论我怎么尝试,我总是以协议“RawRepresentable”结束,它只能用作一般约束,因为它具有自身或关联的类型要求

我已经试过了所有的
where
as
咒语,直到我开始怀疑它是否可以做到


我在Swift 5中,目标是通过调用
CustomType(rawValue:)
来创建新实例,并通过调用
myValue.rawValue

来获取Int值,正如@vadian所说,所有这些类型检查都可以替换为对
UserDefaults.standard.object()
和条件转换的单个调用。此外,
值的类型
属性需要是可选的,以处理未设置属性(或类型不正确)的情况:

用法示例:

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)
枚举方向:Int{
左格=0
案例右=1
}
让key1=DefaultKey(storageKey:“foo”)
key1.value=123
let key2=DefaultKey(存储键:“bar”)
key2.value=.right
打印(key1.value作为任意项)//可选(123)
打印(key2.value作为任意项)//可选(Direction.right)
请注意,如果与非属性列表类型一起使用,这仍然可能崩溃。为了安全起见,您必须将扩展限制为用户默认可存储的类型(整数、浮点、字符串等):

protocol UserDefaultsStorable{}
扩展名Int:UserDefaultsStorable{}
扩展浮点:UserDefaultsStorable{}
// ...
结构默认键{
让storageKey:字符串
}
扩展名DefaultKey,其中T:UserDefaultsStorable{..}
扩展DefaultKey,其中T:RawRepresentable,T.RawValue:UserDefaultsStorable{…}

为什么不简单地用一行
将UserDefaults.standard.object(forKey:self.storageKey)返回为!而不是所有那些丑陋的类型检查?另一方面,您应该检查
nil
和非PropertAllist编译器类型。谢谢。我没有想过尝试通过扩展来专门化类型约束。我需要Objective-C互操作性,这样代码片段就在一个类中,并且初始值设定项提供了一个默认值,这样我就知道它是正确的类型,并且不是空的,我避免返回可选的。我现在已经有了所有要编译的东西(万岁!),但是它并没有一直调用专门的方法!?实际的类/协议困境要复杂得多,所以我需要弄清楚下周会发生什么。。谢谢你的帮助,再次感谢。我会将问题标记为已回答,但我已经发布了一个关于动态分派和泛型的后续问题。。
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 { ... }