如何从Swift KeyPath获取基础值,其类型为KeyPath <root,value!=“”>?

时间:2017-11-02 06:04:23

标签: swift swift4

看看以下代码:

struct Something {
  var s: String! // Implicitly Unwrapped Optional
}

func bind<T, V>(keyPath: WritableKeyPath<T, V?>) {
}

bind(\Something.s)

上面的代码无法编译。如果我们将bind的签名更改为bind<T, V>(keyPath: WritableKeyPath<T, V>),那么编译,但问题是V的类型是String!而我需要获取基础类型,在本例中为String

我们可以解决以下问题:

func bind<T, V>(keypath: WritableKeyPath<T, ImplicitlyUnwrappedOptional<V>>) {
}

不幸的是,文档说不推荐使用ImplicitlyUnwrappedOptional。但是,它未使用@available属性标记为已弃用。

我犹豫是否使用文档所说的类型已被弃用,但我找不到其他方法来实现我所需要的。

  1. 当其类型为Value时,是否有另一种方法可以从WritableKeyPath获取隐式包装的通用WritableKeyPath<T, V!>类型?
  2. 会在某个时候删除ImplicitlyUnwrappedOptional吗?

1 个答案:

答案 0 :(得分:3)

  

当其类型为Value时,是否有另一种方法可以从WritableKeyPath获取隐式包装的通用WritableKeyPath<T, V!>类型?

不是我意识到的。这里的问题真的是\Something.s 不应该是WritableKeyPath<T, V!>。根据{{​​3}}规定的规则,这应该是非法的(IUO是声明的属性;它们不是可以满足通用占位符的实际类型)。

相反,\Something.s应该是WritableKeyPath<T, V?>,所以您的原始代码应该编译。此问题一直是SE-0054

  

是否会在某个时候删除ImplicitlyUnwrappedOptional

是的,这由filed as a bug here

列出
  

由于IUO是声明而不是类型的属性,因此会删除ImplicitlyUnwrappedOptional类型以及长格式ImplicitlyUnwrappedOptional<T>语法。不再允许具有嵌套IUO的类型。其中包括[Int!](Int!, Int!)等类型。

但是,对于Swift 4,这种类型检查器的实现并未完全实现,这就是为什么您仍然可以使用ImplicitlyUnwrappedOptional作为类型来解决问题的原因。 SE-0054,因此您的解决方法将不再在其发布时进行编译。

虽然希望IUO密钥路径错误可以在那时修复。