gpt4 book ai didi

swift - 观察 Swift KeyPaths 列表

转载 作者:行者123 更新时间:2023-11-28 10:34:59 24 4
gpt4 key购买 nike

我有以下代码,它在两个属性上添加了一个观察者:

    obs = []

let xa = self.observe(\CirclePolygon.radius, options: [.new]) { (op, ch) in
callback()
}
obs.append(xa)


let xb = self.observe(\CirclePolygon.origin.x, options: [.new]) { (op, ch) in
callback()
}
obs.append(xb)

它有效,但我不喜欢重复。我试图传递一个 KeyPaths 列表:

    obs = []

let keyPaths = [\CirclePolygon.radius, \CirclePolygon.origin.x]
for keyPath in keyPaths {
let xa = self.observe(keyPath, options: [.new]) { (op, ch) in
callback()
}
obs.append(xa)
}

但我收到编译器错误:无法推断通用参数“值”

有什么办法吗?

最佳答案

首先,请记住 KVO 仅适用于 NSObject 的实例(或子类)。所以如果origin CirclePolygon的属性(property)是 CGPoint或其他一些 struct ,当您尝试注册 \CirclePolygon.origin.x 的观察者时,您将遇到运行时错误, 因为 KVO 不能应用于 x CGPoint 的属性.

其次,你给的关键路径有不同的类型。假设(针对我的第一点)你想观察 radius (一个Double)和origin (CGPoint)。关键路径有不同的类型:

\CirclePolygon.radius   // type: KeyPath<CirclePolygon, Double>
\CirclePolygon.origin // type: KeyPath<CirclePolygon, CGPoint>

如果你试图将它们放在一个数组中,而不明确指定数组的类型,Swift 将按如下方式推导它:

let keyPaths = [\CirclePolygon.origin, \CirclePolygon.radius]
// deduced type of keyPaths: [PartialKeyPath<CirclePolygon>]

它推导出[PartialKeyPath<CirclePolygon>]因为PartialKeyPath<CirclePolygon>是两者最近的共同祖先 KeyPath<CirclePolygon, Double>KeyPath<CirclePolygon, CGPoint> .

所以,在 for在迭代数组的地方循环,你正在传递一个静态类型的对象 PartialKeyPath<CirclePolygon>作为 keyPath observe(_:options:changeHandler:) 的参数方法。不幸的是,该方法是 declared as follows :

public func observe<Value>(
_ keyPath: KeyPath<Self, Value>,
options: NSKeyValueObservingOptions = [],
changeHandler: @escaping (Self, NSKeyValueObservedChange<Value>) -> Void)
-> NSKeyValueObservation

也就是说,该方法需要一个 KeyPath<Self, Value>但你传递的是 PartialKeyPath<Self> , 所以 Swift 会报错。与泛型类型问题相关的 Swift 错误经常出现的情况一样,该错误不是很有帮助。

你不能通过转换来解决这个问题,因为你不能(例如)转换 KeyPath<CirclePolygon, Double>KeyPath<CirclePolygon, Any> .

一种解决方案可能是使用本地函数来封装公共(public)代码,如下所示:

func register(callback: @escaping () -> ()) -> [NSKeyValueObservation] {
func r<Value>(_ keyPath: KeyPath<CirclePolygon, Value>) -> NSKeyValueObservation {
return observe(keyPath, options: []) { (_, _) in
callback()
}
}

return [
r(\.radius),
r(\.origin),
]
}

关于swift - 观察 Swift KeyPaths 列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54029574/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com