Почему NSAnimationContext завершение Handler не работает (иногда)?
// 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
Что мне здесь не хватает?
2 ответа
Это на самом деле не ошибка, но это сбило меня с толку множество раз. Вы должны установить обработчик завершения, прежде чем вызывать анимацию.
Проверьте документацию completionHandler
:
Если задано значение, отличное от nil, контекст завершения Handler гарантированно будет вызван в основном потоке, как только все анимации, впоследствии добавленные в текущую группировку NSAnimationContext, будут завершены или отменены.
Обработчик завершения влияет только на анимацию, добавленную после того, как обработчик завершения был установлен.
В конце также говорится:
Если никакие анимации не добавляются до завершения текущей группировки или если для параметраручки установлено другое значение, обработчик будет вызван немедленно.
В вашем случае анимация не добавляется между установкой обработчика завершения и концом текущей группировки, поэтому ваш обработчик завершения вызывается немедленно.
Правильный код будет:
// 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];
ОК, это ошибка, и я подаю отчет об ошибке на нем. Следующая версия работает отлично
__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];
}];