Используйте CADisplayLink в качестве динамического таймера частоты

Я использую NSTimer для постепенного увеличения / уменьшения некоторых изображений в моем приложении на основе заданной пользователем частоты. Например, если пользователь установил частоту на 5 секунд, то каждые 5 секунд будет выполняться следующий код:

[UIView animateWithDuration:someInterval
                          delay:0
                        options:UIViewAnimationCurveEaseInOut
                     animations:
                        ^{
                            // UI alpha = ... code here
                        }
                     // off...
                     completion:^(BOOL finished){


                         [UIView animateWithDuration:someOtherInterval
                                               delay:yetAnotherValue
                                             options:UIViewAnimationCurveEaseInOut
                                          animations:
                                            ^{
                                                // UI alpha = ... code here
                                            }
                                          completion:nil
                          ];
                     }
     ];

(Точный код не важен, просто общая идея постепенного появления / исчезновения.) Однако, как отмечают многие на Stackru и на различных веб-сайтах, использование NSTimer приводит к заиканию анимаций, потому что оно точно не связано с частота кадров. Поэтому я попытался использовать CADisplayLink вместо этого:

// in viewDidAppear:
timer_count = 0;
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(checkTimer)];
displayLink.frameInterval = 1;
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

-(void)checkTimer
{
    timer_count++;
    if(timer_count >= 1500)
    {
        [self doFadeInOutAnimation];
        timer_count = 0;
    }
}

Это не имеет желаемого эффекта, хотя; изображения просто отображаются в очень быстрой последовательности, вместо того, чтобы ждать, когда они появляются / исчезают каждые 5 секунд.

Есть идеи, как правильно это сделать?

1 ответ

Решение

Ссылка на дисплей будет вызывать ваш метод обратного вызова checkTimer примерно каждые 1/30 секунды. Это все, что он делает. Точное время точно и неизвестно. Отслеживать, сколько времени прошло с того момента, когда он перезвонил вам в последний раз, и решить, означает ли это, что пришло время делать другую анимацию, полностью зависит от вас. Вы должны использовать временную метку отображаемой ссылки, например, чтобы узнать, сколько времени прошло с момента последнего обратного вызова. Вы не делаете это, поэтому ваше время не работает. (Также вы можете тестировать в симуляторе, где CADisplayLink не работает. Вы должны тестировать на устройстве.)

Однако для такого грубого измерения, как "каждые 5 секунд", CADisplayLink является полной тратой. CADisplayLink предназначен для тех случаев, когда вы сами анимируете каждый кадр анимации (то есть вы сами что-то меняете, явно, каждую 1/30 секунды). Это не подходит здесь. Вам все равно, будет ли таймер отключен на 5 секунд, так что ничего страшного. Придерживайтесь вашего текущего кода. Если ваша анимация заикается, выясните, почему; он имеет какое-то отношение к анимации, но не имеет ничего общего с таймером, который, в конце концов, просто говорит "запустить", а затем удаляется. Вы неправильно поняли, что говорят различные посты; они не говорят "не используйте NSTimer", они говорят "не используйте NSTimer, чтобы диктовать отдельные кадры анимации", и вы никогда не делали этого в первую очередь.

Другие вопросы по тегам