Подтвердить что ты не робот

Как правильно остановить и возобновить CADisplayLink?

Я понял большую проблему с CADisplayLink.

У меня есть самый простой EAGLLayer с OpenGL ES 1.1, рисующий вращающийся треугольник для тестирования. Для этого требуется метод цикла выполнения, который вызывается при частоте обновления экрана, поэтому я запускаю runloop следующим образом:

- (void)startRunloop {
    if (!animating) {
        CADisplayLink *dl = [[UIScreen mainScreen] displayLinkWithTarget:self selector:@selector(drawFrame)];
        [dl setFrameInterval:1.0];
        [dl addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        self.displayLink = dl;

        animating = YES;
    }
}

- (void)stopRunloop {
    if (animating) {
        [self.displayLink invalidate];
        self.displayLink = nil;
        animating = NO;
    }
}

Когда запускается тестовое приложение, я вызываю -startRunloop. Когда я нажимаю экран, я вызываю -stopRunloop. Когда я снова нажимаю, я вызываю -STARTRunloop. И так далее. Пинг-понг.

Я измеряю, как часто вызывается метод -drawFrame через 20 секунд, и NSLog it.

  • ПЕРВЫЙ цикл запуска/остановки всегда выполняется на 100%. Я получаю максимальную частоту кадров.

  • Все циклы запуска/остановки SUBSEQUENT показывают только около 80% производительности. Я получаю значительно меньшую частоту кадров. Но: всегда почти то же самое, +/- 2 кадра. Без тенденции к дальнейшему ухудшению даже после еще 50 циклов старта/остановки.

В заключение: СОЗДАНИЕ CADisplayLink, как я делаю выше, в порядке, пока он не будет признан недействительным или приостановлен. После этого любой новый CADisplayLink больше не работает. Даже если он создал новый и точно так же, как раньше. То же самое верно, если я приостанавливаю/возобновляю его, вызывая метод -setPaused: с YES/NO.

Я уверен, что с Allocations и VM Tracker Instruments нет проблемы с управлением памятью. Я также проверил, что метод -invalidate CADisplayLink действительно вызван.

iOS 4.0 на устройстве (iPhone 4).

Почему? Я что-то пропустил?

4b9b3361

Ответ 1

Я думаю, что вы действительно хотите просто приостановить и отключить свою ссылку на изображение.

 - (void)createRunloop {
    CADisplayLink *dl = [[UIScreen mainScreen] displayLinkWithTarget:self selector:@selector(drawFrame)];
    [dl setFrameInterval:1.0];
    [dl addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    self.displayLink = dl;
    // start in running state, your choice.
    dl.paused = NO;
}
- (void)startRunloop {
    self.displayLink.paused = NO;
}
- (void)stopRunloop {
    self.displayLink.paused = YES;
}
- (void)destroyRunloop {
        [self.displayLink invalidate];
        self.displayLink = nil;
}

Ответ 2

Я использую

[displayLink removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

посмотреть, работает ли он для вас

Ответ 3

Вы создаете новый экземпляр ссылки на изображение с каждым стартовым вызовом. Вы пытались просто повторно использовать один и тот же экземпляр?

Кроме того, вы всегда можете просто приостановить отображение ссылки.

Ответ 4

Попробуйте это в Swift,

displayLink?.remove(from: RunLoop.current, forMode: RunLoopMode.defaultRunLoopMode)

Ответ 5

Для Swift 4.2

displayLink.remove(from: RunLoop.current, forMode: RunLoop.Mode.common)