I'm trying to animate the image change in NSImageView. It is a purely academic problem, and I'm staying within the restrictions of a macOS binding framework.
Please, consider the model:
class Model: NSObject {
/// Image object for the NSImageView
@objc dynamic var image: NSImage?
/// The target action for button `A`.
/// Changes the image inside model.
/// The change is not a KVO compliment because such a change is 'inside' the model.
@objc func a() {
self.image = NSImage(named: "a")
}
/// The target action for the button B
/// In the window UI
@objc func b() {
self.image = NSImage(named: "b")
}
}
It is the simplest and strait-forward binding example from the bible (What Are Cocoa Bindings?). The difference I want to achieve is to make the image change process visible to the user.
I will intercept every new image moving to the NSImageView from NSObjectController and transit it with the old one.
class AnimatedImageView: NSImageView {
override func setValue(_ value: Any?, forKey key: String) {
// The code execution is never through this point.
if key == "image" {
self.transition(value as! NSImage?)
} else {
super.setValue(value, forKey: key)
}
}
private func transition(_ newImage:NSImage?) {
let transition = CATransition()
transition.duration = 1
transition.type = .fade
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
self.layer?.add(transition, forKey: nil)
self.image = newImage
}
}
The attempt to override the method setValue(_:forKey:)
was not successful.
Despite this, I know that the method bind(...)
is firing well, and the application itself is working well, except for animation.
What I missed?
Please, find attached the project source is there.
The value binder calls the Objective-C method setObjectValue:
. In Swift, override the objectValue
property.