为啥 NSAnimationContext completionHandler 不起作用(有时)?
Posted
技术标签:
【中文标题】为啥 NSAnimationContext completionHandler 不起作用(有时)?【英文标题】:Why NSAnimationContext completionHandler does not work (sometimes)?为什么 NSAnimationContext completionHandler 不起作用(有时)? 【发布时间】:2014-11-11 11:00:46 【问题描述】:
// wc here is an NSWindowController
[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setDuration:0.5f];
if (duplication)
NSPoint origin = initialSize.origin;
origin.y += initialSize.size.height;
origin = [wc.window cascadeTopLeftFromPoint:origin];
origin.y -= initialSize.size.height;
//[[wc.window animator] setFrameOrigin:origin]; // Why setFrameOrigin and cascadeTopLeftFromPoint are not animated?
initialSize.origin = origin;
[[wc.window animator] setFrame:initialSize display:YES];
// This block should be invoked when all of the animations started above have completed or been cancelled.
// For not to show the edit window till the duplication animation not finished
[NSAnimationContext currentContext].completionHandler = ^
if (edit)
[wc editDocument:self];
else
if (fullScreen)
[wc.window toggleFullScreen:self];
;
[NSAnimationContext endGrouping];
在这种情况下,完成块已执行,但不幸的是不等待窗口重新定位完成,而是立即打开窗口的编辑表并将它们一起移动。
最奇怪的是,在同一个源文件上面的几行相同类型的完成块工作正常:-O
我在这里错过了什么?
【问题讨论】:
【参考方案1】:这实际上不是一个错误,但它让我绊倒了很多次。您必须在调用任何动画之前设置完成处理程序。
【讨论】:
【参考方案2】:查看completionHandler
的文档:
如果设置为非零值,则保证在所有随后添加到当前 NSAnimationContext 分组的动画都已完成或被取消后,在主线程上调用上下文的 completionHandler。
来源:https://developer.apple.com/documentation/appkit/nsanimationcontext/1531132-completionhandler?language=objc
完成处理程序只影响在完成处理程序设置后添加的动画。
最后它还说:
如果在当前分组结束之前没有添加动画——或者completionHandler设置为不同的值——处理程序将立即被调用。
在您的情况下,在设置完成处理程序和当前分组结束之间没有添加动画,因此您的完成处理程序会立即被调用。
正确的代码是:
// wc here is an NSWindowController
[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setDuration:0.5f];
// This block should be invoked when all of the animations started above have completed or been cancelled.
// For not to show the edit window till the duplication animation not finished
[NSAnimationContext currentContext].completionHandler = ^
if (edit)
[wc editDocument:self];
else
if (fullScreen)
[wc.window toggleFullScreen:self];
;
if (duplication)
NSPoint origin = initialSize.origin;
origin.y += initialSize.size.height;
origin = [wc.window cascadeTopLeftFromPoint:origin];
origin.y -= initialSize.size.height;
//[[wc.window animator] setFrameOrigin:origin]; // Why setFrameOrigin and cascadeTopLeftFromPoint are not animated?
initialSize.origin = origin;
[[wc.window animator] setFrame:initialSize display:YES];
[NSAnimationContext endGrouping];
【讨论】:
【参考方案3】:好的,这是一个错误,我提交了一个错误报告。下一个版本完美运行
__block NSRect newPosition(initialSize);
[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context)
[context setDuration:0.5f];
if (duplication)
NSPoint origin = newPosition.origin;
origin.y += newPosition.size.height;
origin = [wc.window cascadeTopLeftFromPoint:origin];
origin.y -= newPosition.size.height;
//[[wc.window animator] setFrameOrigin:origin]; // Why setFrameOrigin and cascadeTopLeftFromPoint are not animated?
newPosition.origin = origin;
[[wc.window animator] setFrame:newPosition display:YES];
completionHandler:^
// This block will be invoked when all of the animations
// started above have completed or been cancelled.
if (edit)
[wc editDocument:self];
else
if (fullScreen)
[wc.window toggleFullScreen:self];
];
【讨论】:
以上是关于为啥 NSAnimationContext completionHandler 不起作用(有时)?的主要内容,如果未能解决你的问题,请参考以下文章
未使用 NSAnimationContext 调用 CAAnimation animationDidStop
Swift MacOS NSAnimationContext 不遵循其持续时间