NSFindow setFrame:display:animate: запускаться одновременно с другими анимациями

Я использую NSWindow без полей для создания слайд-меню, которое вы можете найти во многих приложениях IOS. В настоящее время я использую setFrame:display:animate: с двумя предопределенными ритами для создания скользящего эффекта, а также у меня есть анимация, которая затеняет фон основного окна, который в данный момент запускается после того, как окно завершило анимацию.

Я бы очень хотел запустить обе эти анимации одновременно. Однако setFrame: display: animate, похоже, блокирует весь другой код до его завершения.

Есть ли способ переопределить эту функцию setFrame: display: animate? Или кто-нибудь может порекомендовать обходной путь?

У меня есть методы работы, которые запускают [[self animator]setFrame:display:], но я бы предпочел использовать setFrame: display: animate, потому что он широко представлен в моем текущем коде и его легко настроить на длительность.

Некоторый код:

//Currently used to animate the window
-(void)showPopWindow{
    [self selectAnimationTimeFor:NCpOpen];    
    [self setFrame:_initialRect display:YES];
    [self makeKeyAndOrderFront:NSApp];
    [self setFrame:_finalRect display:YES animate:YES];
}

И это другая анимация, которая у меня есть, которая в настоящий момент запускается после завершения setFrame (обратите внимание, что она выполняется на уровне NSView).

//...
[layer setBackgroundColor:CGColorCreateGenericRGB(0, 0, 0, 0.5)];

CABasicAnimation *fadeInBackground = [CABasicAnimation animationWithKeyPath:@"opacity"];
fadeBackground.duration = [self openAnimationResizeTime];
fadeBackground.fromValue = [NSNumber numberWithFloat:0.0f];
fadeBackground.toValue = [NSNumber numberWithFloat:1.0f];

[layer addAnimation:fadeInBackground forKey:@"opacity"];

2 ответа

Решение

Решил проблему, используя NSAnimationContext вместе с [[self animator]setAlphaValue:], что позволяет мне запускать одновременные анимации и затем выполнять блок по завершении.

Документация:

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSAnimationContext_class/Introduction/Introduction.html:

Рабочий код:

// To avoid a strong reference cycle to self in block
__weak typeof(self)weakSelf = self;

[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
    [context setDuration: myDuration];
    [[weakSelf animator] setFrame:_initialRect display:YES];

    // ... other animations

} completionHandler:^{
    NSLog(@"done");
    [[weakSelf overCastView] removeFromSuperview];
    weakSelf.overCastView = nil;
}];

Следующее сработало для меня (с благодарностью за этот ответ). Я думаю, что это более "правильное" решение из-за явного NSAnimationNonblocking:

NSRect myNewFrame = NSMakeRect(0, 0, 123, 456);

NSDictionary* windowResize = [NSDictionary dictionaryWithObjectsAndKeys: window, NSViewAnimationTargetKey, [NSValue valueWithRect: myNewFrame], NSViewAnimationEndFrameKey, nil];
NSArray* animations = [NSArray arrayWithObjects:windowResize, nil];
NSViewAnimation* animation = [[NSViewAnimation alloc] initWithViewAnimations: animations];

[animation setAnimationBlockingMode: NSAnimationNonblocking];
[animation setAnimationCurve: NSAnimationEaseIn];
[animation setDuration: 0.4];     
[animation startAnimation]; 
Другие вопросы по тегам