Ho scoperto un grosso problema con CADisplayLink.Come interrompere e riprendere correttamente un CADisplayLink?
Ho l'EAGLLayer più semplice con OpenGL ES 1.1 che disegna un triangolo rotante per il test. Questo ha bisogno di un metodo ciclo corsa per essere chiamato a frequenza di aggiornamento dello schermo, in modo da avviare il runloop in questo modo:
- (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;
}
}
Quando i lanci di applicazione di test, mi chiamano -startRunloop. Quando tocco lo schermo, chiamo -stopRunloop. Quando tocco di nuovo, chiamo -startRunloop. E così via. Ping Pong.
Sto misurando la frequenza con cui il metodo -drawFrame viene chiamato in 20 secondi e NSLog.
Il primo ciclo di avvio/arresto funziona sempre al 100%. Ottengo il frame rate massimo.
Tutti i cicli di avvio/arresto SUBSEQUENT mostrano solo circa l'80% delle prestazioni. Ottengo un frame rate significativamente più piccolo. Ma: sempre quasi esattamente lo stesso, +/- 2 fotogrammi. Senza tendenza a degradare ulteriormente anche dopo altri 50 cicli di avvio/arresto.
In conclusione: la creazione di un CADisplayLink come faccio io sopra va bene, fino a quando è invalidata o in pausa. Dopodiché, qualsiasi nuovo CADisplayLink non funziona più bene. Anche se è stato creato nuovo e nello stesso identico modo di prima. Lo stesso è vero se sospendo/riprendo chiamando il metodo -setPaused: con YES/NO.
Mi sono assicurato che con Allocations e VM Tracker Instruments non ci sia alcun problema di gestione della memoria. Ho anche verificato che il metodo -invalidate di CADisplayLink venga davvero chiamato.
iOS 4.0 sul dispositivo (iPhone 4).
Perché è quello? Mi sto perdendo qualcosa?
suona come un bug. Penso che tu debba presentare una segnalazione di bug ad Apple. –
Ho lo stesso problema. Non ho bisogno che il DisplayLink funzioni sempre, ma sembra che non abbia una scelta. Quindi ora sto usando solo flag nel selettore del gestore invece di usare isPaused. –