繁体   English   中英

Swift 5 存储和传递 KeyPath

[英]Swift 5 storing and passing KeyPaths

假设我有以下课程:

class User: NSObject {
  var name = "Fred"
  var age = 24
  var email = "fred@freddy.com"
  var married = false
}

我希望能够编写一个通用函数,该函数接受已知类类型的KeyPath列表,读取值并打印到屏幕。 问题是,我无法编译以下代码,因为KeyPathValue的类型未知,并且每次都会不同。 我必须做什么才能使这项工作普遍有效?

考虑以下:

struct KeyPathProperties<T> {
  var name: String
  var relatedKeyPaths: [KeyPath<T, Any>]
}

extension KeyPath where Root == User {
  var properties: KeyPathProperties<Root> {
    switch self {
      case \Root.name:
        return KeyPathProperties(name: "name", relatedKeyPaths: [\Root.age, \Root.email])
      default:
        fatalError("Unknown key path")
    }
  }
}

此行无法编译:

return KeyPathProperties(name: "name", relatedKeyPaths: [\Root.age, \Root.email])

出现此错误:

Cannot convert value of type 'KeyPath<User, Int>' to expected element type 'KeyPath<User, Any>'

这就是我希望能够做的,例如:

let myUser = User()

var keyPathProps = KeyPathProperties(name: "name", relatedKeyPaths: [\User.age, \User.email])

for keyPath in props.relatedKeyPaths {
  print("Value: \(myUser[keyPath: keyPath])")
}

以上当然不会编译。 基本上我想在运行时将 keyPaths 存储在一个数组中,所以我可以在某个时间点从User获取值。 我需要知道我是否可以以某种方式重写上述内容,编译器可以在运行时安全且正确地确定 keyPath 值的类型。

这是一个更复杂的架构问题的概念用例,我正试图用更少的代码来解决。

更多信息:

在运行时,我希望跟踪被修改的属性 - 这些属性保存在每个对象/实例的 modifiedProps 数组中。 在运行时的某个时候,我希望能够枚举这个 KeyPath 数组并像这样打印它们的值:

for modifiedKeyPath in self.modifiedProps { 
  print ("\(self[keyPath: modifiedKeyPath])" 
}

简而言之 - 我需要能够在KeyPathProperties捕获 KeyPath 的通用类型。 我如何实现这一目标?

边注:通过使用基于 Swift 3 样式字符串的 KeyPaths(通过将@objc添加到类属性),我已经可以轻松实现这一点。 我可以将 keyPaths 数组存储为字符串,然后执行以下操作:

let someKeyPath = #keyPath(User.email)
...

myUser.value(forKeyPath: someKeyPath)

我只是不能用 Swift 4 KeyPaths 一般地做到这一点。

该错误告诉您您的误解是什么:

Cannot convert value of type 'KeyPath<User, Int>' 
    to expected element type 'KeyPath<User, Any>'

您似乎认为您可以在需要KeyPath<User, Any>地方使用KeyPath<User, Int> ,表面上是因为 Int 是 Any。 但事实并非如此。 这些是泛型类型,泛型类型不是协变的——也就是说,没有基于参数化类型的泛型替换原则。 这两种类型实际上是不相关的。

如果您需要一组键路径而不考虑其参数化类型,则需要一个 PartialKeyPath 或 AnyKeyPath 数组。 在您的用例中,根对象似乎始终相同,因此您可能需要 PartialKeyPath。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM