使用这篇伟大帖子中的技术,对SwV3中的KVO值“很容易”......
https://stackoverflow.com/a/25219216/294884
我如何看待UIView的alpha?
目标:想象一个小视图的屏幕V.屏幕有一个大的桌面视图。每个单元格都有一个小视图CV。
我希望每个CV跟随 1 V的alpha,实际上是在V的alpha动画期间。
(我能想到的唯一真正的替代品是CADisplayLink细胞并轮询V的alpha,这种情况很糟糕。)
1 原因是什么?这是在单元格之间同步alpha变化的唯一方法。
注意正如Rob在下面解释的那样,实际上图层的alpha不会设置动画。 (它只是在动画开始时“立即”设置为新值。)实际上,您必须遵循表示层。这是一个逆向过程的例子,从你希望每次抽奖的地方拉出来
let d = CADisplayLink(target: self, selector: #selector(ThisClassName.updateAlpha))
d.add(to: RunLoop.current, forMode: RunLoopMode.commonModes)
func updateAlpha() {
let a = leader.layer.presentation()?.value(forKey: "opacity") as! CGFloat
follower.alpha = a
}
答案 0 :(得分:9)
这不是KVO的理想用例。您可能更愿意转到正在更改alpha
的代码并让它对其他视图进行必要的更新(或者构建一些更通用的接口;除了KVO之外的其他视图)。
另请注意,如果您正在处理动画,则alpha
的KVO可能仅识别动画的启动,而不是观察动画期间飞行中的变化。 (通常使用presentation
中的presentationLayer
/ CADisplayLink
或类似内容来捕获这些类型的更改。)
话虽如此,是的,你可以观察alpha
财产。所以,在Swift 3中,只需定义上下文:
private var observerContext = 0
然后添加观察者:
observedView.addObserver(self, forKeyPath: "alpha", options: .new, context: &observerContext)
然后实现你的观察者:
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
guard context == &observerContext else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
return
}
// do what you want here
}
注意,请记住删除观察者。例如,您可以在deinit
中执行此操作:
deinit {
observedView.removeObserver(self, forKeyPath: "alpha", context: &observerContext)
}
注意,在Swift 4中,这个过程有点简化。定义token
属性以跟踪观察者:
private var token: NSKeyValueObservation?
然后观察alpha
属性:
token = observedView.observe(\.alpha) { [weak self] object, change in
// do something
}
注意使用[weak self]
来确保闭包不会导致强引用周期。显然,如果你没有在那个闭包中引用self
,那就不需要了。
但基于块的模式的优点在于:(a)当token
超出范围时,观察者将被自动删除,因此不需要特殊的deinit
例程; (b)observedView
的可观察密钥现在是强类型的,避免了密钥中的简单印刷错误; (c)因为观察者与这种封闭有关,我们不再需要对观察者的背景进行检查,如果这不是我们的背景,请致电self
。