3

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

我在这里想念什么?

4

3 回答 3

6

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

于 2016-02-09T12:27:34.563 回答
2

检查文档completionHandler

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

来源: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];
于 2019-05-23T15:09:50.947 回答
0

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

__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];
}];
于 2014-11-11T11:15:32.787 回答