Возможно, что NSTimer
убивает вашу производительность.Core Animation имеет богатую поддержку для контроля времени анимации по протоколу CAMediaTiming
, и вы должны воспользоваться этим в своем приложении.Вместо использования прокси аниматора и NSAnimationContext
, попробуйте использовать Core Animation напрямую.Если вы создадите CABasicAnimation
для каждого изображения и установите его beginTime
, это приведет к задержке запуска анимации.Кроме того, чтобы задержка работала так, как вы хотите, вы должны обернуть каждую анимацию в CAAnimationGroup
с ее duration
, установленным на общее время всей анимации.
Использование свойства frame
можеттакже будет способствовать замедлению.Мне действительно нравится использовать свойство transform
в CALayer
в таких ситуациях, когда вы делаете «открывающую» анимацию.Вы можете разместить свои изображения в IB (или в коде) на их конечных позициях, и непосредственно перед тем, как окно станет видимым, изменить их преобразования в исходную позицию анимации.Затем вы просто сбрасываете все преобразования на CATransform3DIdentity
, чтобы вернуть интерфейс в нормальное состояние.
У меня есть пример в моем грядущая книга Core Animation это очень похоже на то, что вы пытаетесь сделать.Он оживляет 30 NSImageView
с одновременно без пропущенных кадров.Я изменил пример для вас и поместил его на github .Вот наиболее важные фрагменты кода, в которых убраны посторонние элементы пользовательского интерфейса:
Преобразование слоев в их начальное положение
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// ... SNIP ... //
//Start with all of the images at the origin
[CATransaction begin];
[CATransaction setDisableActions:YES];
for (CALayer *imageLayer in [[[self imageContainer] layer] sublayers]) {
CGPoint layerPosition = [layer position];
CATransform3D originTransform = CATransform3DMakeTranslation(20.f - layerPosition.x, -layerPosition.y, 0.f);
[imageLayer setTransform:originTransform];
}
[CATransaction commit];
}
Анимация преобразования обратно к идентификатору
- (IBAction)runAnimation:(id)sender {
CALayer *containerLayer = [[self imageContainer] layer];
NSTimeInterval delay = 0.f;
NSTimeInterval delayStep = .05f;
NSTimeInterval singleDuration = [[self durationStepper] doubleValue];
NSTimeInterval fullDuration = singleDuration + (delayStep * [[containerLayer sublayers] count]);
for (CALayer *imageLayer in [containerLayer sublayers]) {
CATransform3D currentTransform = [[imageLayer presentationLayer] transform];
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform"];
anim.beginTime = delay;
anim.fromValue = [NSValue valueWithCATransform3D:currentTransform];
anim.toValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
anim.fillMode = kCAFillModeBackwards;
anim.duration = singleDuration;
CAAnimationGroup *group = [CAAnimationGroup animation];
group.animations = [NSArray arrayWithObject:anim];
group.duration = fullDuration;
[imageLayer setTransform:CATransform3DIdentity];
[imageLayer addAnimation:group forKey:@"transform"];
delay += delayStep;
}
}
У меня также есть видео на YouTube примера в действии, если вы хотите его проверить.