ios - 如何检测类型对于通用 propertyWrapper 是可选的

标签 ios swift generics nsuserdefaults property-wrapper

我正在为 UserDefaults 创建一个属性包装器。

我想要实现的是:

  • 为属性设置非零值会将其存储在用户默认值中。
  • 设置 nil 将从 UserDefault 中删除该对象。

但是下面的代码会引发编译器错误:

Initializer for conditional binding must have Optional type, not 'T'

@propertyWrapper
struct UserDefault<T> {
    let key: String
    let defaultValue: T

    init(_ key: String, defaultValue: T) {
        self.key = key
        self.defaultValue = defaultValue
    }

    var wrappedValue: T {
        get { UserDefaults.standard.value(forKey: key) as? T ?? defaultValue }
        set {
            if let newValue = newValue {
                UserDefaults.standard.setValue(newValue, forKey: key)
            } else {
                UserDefaults.standard.removeObject(forKey: key)
            }
        }
    }
}

// Declaration
@UserDefault("key", defaultValue: nil)
static var newUserDefaultValue: String

有什么方法可以判断T是可选的吗?因为我可以从 UserDefaults 中删除 key 。如果不是如何达到预期的输出?

最佳答案

您的代码中有两个问题:

1) 在您的情况下,wrappedValuedefaultValue 应该是可选的:

struct UserDefault<T> {
  let key: String
  let defaultValue: T? // defaultValue should be optional

  // defaultValue should be optional
  init(_ key: String, defaultValue: T?) {
    self.key = key
    self.defaultValue = defaultValue
  }

  // wrappedValue should also be optional
  var wrappedValue: T? {
    get { UserDefaults.standard.value(forKey: key) as? T ?? defaultValue }
    set {
      if let newValue = newValue {
        UserDefaults.standard.setValue(newValue, forKey: key)
      } else {
        UserDefaults.standard.removeObject(forKey: key)
      }
    }
  }
}

2) 如果使用 nil defaultValue 进行初始化,则应为编译器指定类型 T:

// Type T should be expicitly specified. For example as String
let valueWithNilDefault = UserDefault<String>("key", defaultValue: nil)

// Type T will be determined during compile time as Int
let valueWithDefault = UserDefault("key", defaultValue: 15)

关于ios - 如何检测类型对于通用 propertyWrapper 是可选的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58802347/

相关文章:

iOS:通过在图像之间混合来平滑按钮发光效果

c# - 类型参数必须是逆变有效的

ios - Swift 3 JSON 解析异常

swift - 居中对齐 stackView 同时保持固定间距

swift - 条件协议(protocol)一致性?

objective-c - Swift 函数覆盖 Objective-C 方法

ios - iTunes Connect bundle ID问题

ios - 如何在没有动画的情况下弹出到 View Controller

ios - UISearchController 导致黑屏 Swift 2.0

ios - AVPlayer removeTimeObserver 使应用程序崩溃(swift 3)