为什么NSAnimationContext completionHandler不起作用(有时)?

时间:2014-11-11 11:00:46

标签: objective-c completionhandler nsanimationcontext


    // 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];

在这种情况下,执行完成块但不幸的是不等待窗口重新定位完成,而是立即打开窗口的编辑表并将它们一起移动。

最奇怪的是,相同源文件中的几行相同类型的completition块工作正常:-O

我在这里缺少什么?

3 个答案:

答案 0 :(得分:5)

这实际上不是一个错误,但它让我绊倒了很多次。您必须在调用任何动画之前设置完成处理程序

答案 1 :(得分:2)

检查completionHandler的文档:

  

如果设置为非nil值,则保证随后添加到当前NSAnimationContext分组中的所有动画完成或被取消后,将在主线程上立即调用上下文的completionHandler。 / p>

来源: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];

答案 2 :(得分:0)

好的,这是一个BUG,我提交了一个错误报告。下一个版本完美无缺

__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];
}];