假设我有以下课程:
class User: NSObject {
var name = "Fred"
var age = 24
var email = "fred@freddy.com"
var married = false
}
我希望能够编写一个通用函数,该函数接受KeyPath
已知类类型的 s 列表,读取值并打印到屏幕。问题是,我无法编译以下代码,因为KeyPath
's的类型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 数组中。在运行时的某个时刻,我希望能够枚举这个 KeyPaths 数组并像这样打印它们的值:
for modifiedKeyPath in self.modifiedProps {
print ("\(self[keyPath: modifiedKeyPath])"
}
简而言之 - 我需要能够在KeyPathProperties
. 我如何实现这一目标?
旁注:我已经可以通过使用基于 Swift 3 样式字符串的 KeyPaths 轻松实现这一点(通过添加@objc
到类属性中)。我可以将 keyPaths 数组存储为字符串,然后再执行以下操作:
let someKeyPath = #keyPath(User.email)
...
myUser.value(forKeyPath: someKeyPath)
我一般不能用 Swift 4 KeyPaths 做到这一点。