It's "easy" to KVO a value in Swift3, using the technique in this great post...
https://stackoverflow.com/a/25219216/294884
How do I KVO the alpha of a UIView?
Goal: imagine a screen with a small view V. Screen has a large table view. Each cell has a small view CV.
I want each CV to follow1 the alpha of V, actually during an animation of the alpha of V.
(The only real alternate I can think of is to CADisplayLink the cells and poll the alpha of V, which kind of sucks.)
1Reason for that? It's the only way to sync alpha changes across cells.
Note Just as Rob explains below, in fact the alpha of a layer does not animate. (It just sets "instantly" to the new value at the beginning of an animation.) In fact you have to follow the presentation layer. Here's an example of the converse process, pulling it from where you want every draw
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
}
This is not an ideal use-case of KVO. You'd probably prefer to go to the code that is changing the
alpha
and have it do the necessary updates of the other views (or build some interface to do that more generically; something other than KVO).Also note that if you're dealing with animations, the KVO of
alpha
may only identify the initiation of the animation, not observing the changes mid-flight during the animation. (Those sorts of changes are generally captured with thepresentation
/presentationLayer
in aCADisplayLink
or the like.)Having said that, yes, you can observe
alpha
property. So, in Swift 3, just define context:And then add the observer:
and then implement your observer:
Note, remember to remove the observer. For example, you might do that in
deinit
:Note, in Swift 4, this process is simplified a bit. Define a
token
property to keep track of your observer:And then observe the
alpha
property:Note the use of
[weak self]
to ensure the closure doesn't cause strong reference cycle. Obviously, if you're not referencingself
in that closure, that is not needed.But the virtue of the block based pattern is that (a) when the the
token
falls out of scope, the observer is automatically removed, so no specialdeinit
routine is needed; (b) the observable keys forobservedView
are now strongly typed, avoiding simple typographical errors in the keys; and (c) because the observer is linked to this closure, we no longer have to do that check of the context of the observer and callself
if this wasn't our context.