Я использую @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
Чего мне не хватает?Любые мысли о том, как я могу решить эту проблему?