[英]Swift 5 storing and passing KeyPaths
假设我有以下课程:
class User: NSObject {
var name = "Fred"
var age = 24
var email = "fred@freddy.com"
var married = false
}
我希望能够编写一个通用函数,该函数接受已知类类型的KeyPath
列表,读取值并打印到屏幕。 问题是,我无法编译以下代码,因为KeyPath
的Value
的类型未知,并且每次都会不同。 我必须做什么才能使这项工作普遍有效?
考虑以下:
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.