0

我正在为UserDefaults.

我想要实现的是:

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

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

条件绑定的初始化程序必须具有可选类型,而不是“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 中删除密钥。如果不是如何达到预期的输出?

4

1 回答 1

0

您的代码中有两个问题:

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

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)
于 2019-11-11T16:20:50.943 回答