【发布时间】:2021-03-06 21:34:39
【问题描述】:
我有一个类似的对象:
class MyObject {
var title:String? = nil
var value:Int? = nil
var otherData:[String] = []
}
我正在尝试存储一个异构的更新数组,以便以后可以使用它们来设置值。像这样。
class SomeFormThing {
func getUpdates() -> [WritableKeyPath<MyObject, Any> : Any] {
var updates:[WritableKeyPath<MyObject, Any> : Any]
updates[\MyObject.title] = "New Title"
updates[\MyObject.value] = 0
updates[\MyObject.value] = ["Other", "Values"]
return updates
}
}
class SyncManager {
var form:SomeFormThing = SomeFormThing()
var sync:MyObject = MyObject()
func updateValues() {
let updates = form.getUpdates()
for key in updates.keys {
sync[forKeyPath: key] = updates[key]
}
}
}
但是,这在 getUpdates() 中读取 Cannot convert value of type 'WritableKeyPath<MyObject, String?>' to expected argument type 'WritableKeyPath<MyObject, Any>' 的行中当然存在编译问题。
需要有一组异构的可写键路径,然后我可以使用它们来设置值。鉴于泛型通常是如何工作的,我不明白为什么 String 不能等同于 Any 泛型,因为该类型是向下转换的。
【问题讨论】:
-
Swift 泛型不是协变的,你不能强制转换它们。
-
@JoakimDanielson 我已经尝试过了。这会产生同样的问题。
-
@vadian 那么我将如何完成我正在尝试的事情,一个带有值的键路径的异构字典。
-
基本上你不能。这一直是关键路径的问题,因为这是泛型的工作方式。当然,您可以键入擦除 - 这正是部分关键路径的用途 - 但这会带给您什么?基本上,您在这里想要做的是违背 Swift 的整体精神:关键路径为您提供类型安全,而您要求将其丢弃。
-
@matt 所以,本质上,除非您可以遵循 NSObject 并使用带有 .setValue 的字符串键,否则 Swift 无法根据对象的键:值对来反身地和动态地设置值?而且,在这种情况下,我不能使用 NSObject 的 .setValue,因为它不适用于可选项。这似乎是对基于反射的代码的巨大疏忽。
标签: swift keypaths swift-keypath