【发布时间】:2020-01-20 09:28:11
【问题描述】:
我正在使用@propertyWrapper 来减少我的UserDefaults 样板,如下所示……
enum PreferenceKey: String, CaseIterable {
case enumName, stringName
}
@propertyWrapper
struct Prefs<T> {
let key: PreferenceKey
var wrappedValue: T? {
get {
UserDefaults.object(for: key)
}
set {
UserDefaults.set(newValue, for: key)
}
}
}
struct Preferences {
@Prefs(key: .enumName) static var enumName: Name?
@Prefs(key: .stringName) static var stringName: String?
}
extension UserDefaults {
static func object<T>(for key: PreferenceKey) -> T? {
standard.object(forKey: key.rawValue) as? T
}
static func object<T: RawRepresentable>(for key: PreferenceKey) -> T? where T.RawValue == String {
if let value = standard.object(forKey: key.rawValue) as? String {
return T(rawValue: value)
}
return nil
}
static func set<T: RawRepresentable>(_ value: T, for key: PreferenceKey) {
print("Set Raw Value \(value)")
standard.set(value.rawValue, forKey: key.rawValue)
}
static func set<T>(_ value: T, for key: PreferenceKey) {
print("Set Value \(value)")
standard.set(value, forKey: key.rawValue)
}
}
这在设置常规属性列表类型时效果很好……
Preferences.stringName = "Fred"
// Set Value Optional("Fred")
print(Preferences.stringName)
// Optional("Fred")
但是当尝试设置一个RawRepresentable 的值时,它失败了……
Preferences.enumName = .Fred
// Set Value Optional(__lldb_expr_10.Name.Fred)
// libc++abi.dylib: terminating with uncaught exception of type NSException
它不会调用UserDefaults.set( 的最具体版本,而是调用非具体版本。
只是打电话
UserDefaults.set(Name.Fred, for: .enumName)
工作正常。在这种情况下,它会调用最具体的函数。
经过进一步测试,这似乎不是@propertyWrapper 问题。以下顶级函数也无法调用更具体的通用函数。似乎某些类型信息在某处丢失了
func set<T>(_ value: T?) {
UserDefaults.set(value, for: .enumName)
}
set(Name.Fred)
// Set Value Optional(__lldb_expr_5.Name.Fred)
// libc++abi.dylib: terminating with uncaught exception of type NSException
我错过了什么?关于如何解决这个问题的任何想法?
【问题讨论】: