Reputation: 1041
This is as simple as can be so I can't for the life of me find what's wrong, I looked through the documentation as a guide but it still didn't work. I have a view inside a larger view. An IBAction
is supposed to fade out the inner view... that's it. Here's what I've got:
NSViewAnimation *theAnim;
NSMutableDictionary *viewDict;
// Create the attributes dictionary for the view.
viewDict = [NSMutableDictionary dictionaryWithCapacity:2];
// Set the target object to be the view.
[viewDict setObject:_innerView forKey:NSViewAnimationTargetKey];
// Set this view to fade out
[viewDict setObject:NSViewAnimationFadeOutEffect forKey:NSViewAnimationEffectKey];
theAnim = [[NSViewAnimation alloc] initWithViewAnimations:@[viewDict]];
// Set some additional attributes for the animation.
[theAnim setDuration:1.0];
// Run the animation.
[theAnim startAnimation];
I checked the viewDict
and theAnim
with NSLog
and neither are nil
. I pretty much copied this from an old program I had where this was working, can't find what's wrong now.
I'm using Xcode 5.1.1.
Upvotes: 33
Views: 19493
Reputation: 6730
The Swift version which successfully working.
// Extension
extension NSViewAnimation {
public static func make(target: NSView, effect: NSViewAnimation.EffectName) -> NSViewAnimation {
var animationDict: [NSViewAnimation.Key : Any] = [:]
animationDict[.target] = target
animationDict[.effect] = effect
let viewAnimation = NSViewAnimation(viewAnimations: [animationDict])
return viewAnimation
}
}
// Custom subclass of NSView
class MySimpleView: NSView {
override func draw(_ dirtyRect: NSRect) {
NSColor.brown.setFill()
dirtyRect.fill()
}
func animateFadeOut() {
let animation = NSViewAnimation.make(target: self, effect: .fadeOut)
animation.start()
}
}
// Usage
let containerView = NSView()
let view = MySimpleView(frame: CGRect(x: 20, y: 20, width: 60, height: 60))
view.autoresizingMask = []
containerView.addSubview(view)
// At some point later
view.animateFadeOut() // Works as expected.
Upvotes: 0
Reputation: 19349
For those looking for a Swift version instead:
NSAnimationContext.runAnimationGroup({ context in
context.duration = 1
self.view.animator().alphaValue = 0
}, completionHandler: {
self.view.isHidden = true
self.view.alphaValue = 1
})
For layer-backed views, this is enough:
view.animator().isHidden = true
For those already on Swift 5.3 or above, you can leverage the new Multiple Trailing Closures syntax sugar here for an even cleaner version:
NSAnimationContext.runAnimationGroup { context in
context.duration = 1
self.view.animator().alphaValue = 0
} completionHandler: {
self.view.isHidden = true
self.view.alphaValue = 1
}
Upvotes: 13
Reputation: 90681
The modern approach is much easier:
[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
context.duration = 1;
view.animator.alphaValue = 0;
}
completionHandler:^{
view.hidden = YES;
view.alphaValue = 1;
}];
If the view hierarchy is layer-backed, it's actually sufficient to do:
view.animator.hidden = YES;
Upvotes: 85