2010-04-07 9 views
9

Qualcuno sa o ha dei buoni link che spiegano cosa fa il ciclo degli eventi di iPhone sotto il cofano?Ciclo evento personalizzato e controlli UIKit. Che extra magica fa il ciclo degli eventi di Apple?

Stiamo utilizzando un ciclo di eventi personalizzato nel nostro framework di giochi per iPhone basato su OpenGL. Chiama il nostro sistema di rendering del gioco, chiama presentRenderbuffer e pompa gli eventi utilizzando CFRunLoopRunInMode. Vedi il codice qui sotto per i dettagli.

Funziona bene quando non utilizziamo i controlli UIKit (come prova, prova Facetap, il nostro primo gioco rilasciato).

Tuttavia, quando si utilizzano i controlli UIKit, tutto quasi funziona, ma non del tutto. Nello specifico, lo scorrimento dei controlli di UIKit non funziona correttamente.

Ad esempio, consideriamo lo scenario seguente.

  • Mostriamo UIImagePickerController in cima alla nostra vista.
  • UIImagePickerController copre la nostra vista personalizzata
  • Mettiamo anche in pausa il nostro rendering, ma continuiamo ad usare il ciclo di eventi personalizzato.

Come detto, tutto funziona, tranne lo scorrimento.

  • Il prelievo delle foto funziona.
  • Drill in giù per lavori di album di foto e animazioni di transizione sono liscio.
  • Quando si tenta di scorrere la visualizzazione dell'album fotografico, la vista segue il dito.

Problema: quando si scorre, lo scorrimento si interrompe immediatamente dopo aver sollevato il dito. Normalmente, continua senza intoppi in base alla velocità del movimento, ma non quando si utilizza il ciclo di eventi personalizzato. Sembra che il ciclo degli eventi di iPhone stia facendo qualche magia legata allo scrolling UIKit che non abbiamo implementato noi stessi.

Ora, possiamo far sì che i controlli UIKit funzionino perfettamente e dandy insieme al nostro sistema utilizzando il ciclo degli eventi di Apple e chiamando il nostro rendering tramite i callback NSTimer. Tuttavia, mi piacerebbe ancora capire, che cosa potrebbe accadere all'interno del ciclo degli eventi di iPhone che non è implementato nel nostro ciclo di eventi personalizzati.

- (void)customEventLoop { OBJC_METHOD; 
    float excess = 0.0f; 
    while(isRunning) { 
    animationInterval = 1.0f/openGLapp->ticks_per_second(); 

    // Calculate the target time to be used in this run of loop 
    float wait = max(0.0, animationInterval - excess); 
    Systemtime target = Systemtime::now().after_seconds(wait); 

    Scope("event loop"); 

    NSAutoreleasePool* pool = [[ NSAutoreleasePool alloc] init]; 

    // Call our own render system and present render buffer 
    [self drawView]; 
    // Pump system events 
    [self handleSystemEvents:target]; 

    [pool release]; 

    excess = target.seconds_to_now(); 
    } 
} 

- (void)drawView { OBJC_METHOD; 

    // call our own custom rendering 
    bool bind = openGLapp->app_render(); 

    // bind the buffer to be THE renderbuffer and present its contents 
    if (bind) { 
    opengl::bind_renderbuffer(renderbuffer); 
    [context presentRenderbuffer:GL_RENDERBUFFER_OES]; 
    } 
} 

- (void) handleSystemEvents:(Systemtime)target { OBJC_METHOD; 
    SInt32 reason = 0; 
    double time_left = target.seconds_since_now(); 
    if (time_left <= 0.0) { 
    while((reason = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, TRUE)) == kCFRunLoopRunHandledSource) {} 
    } else { 
    float dt = time_left; 
    while((reason = CFRunLoopRunInMode(kCFRunLoopDefaultMode, dt, FALSE)) == kCFRunLoopRunHandledSource) { 
     double time_left = target.seconds_since_now(); 
     if (time_left <= 0.0) break; 
     dt = (float) time_left; 
    } 
    } 
} 

risposta

4

Se NSLog[[NSRunLoop currentRunLoop] currentMode] da [UIScrollView setContentOffset:] quando [UIScrollView isDecelerating] è vero si vedrà UITrackingRunLoopMode.

In generale, il sistema utilizzerà le modalità oltre a kCFRunLoopDefaultMode nel ciclo di esecuzione del thread principale dell'interfaccia utente, solo alcune delle quali sono documentate. L'unico modo per ottenere un comportamento completo del sistema è quello di cooperare con il ciclo di esecuzione del sistema sul thread principale.

Si potrebbe provare a utilizzare un NSTimer e lasciare che il sistema ti chiami invece di chiamare CFRunLoopRunInMode tu stesso. Un NSTimer è libero di funzionare nel tempo e quando non viene mostrata un'altra interfaccia utente, il ciclo di esecuzione del sistema non farebbe altro che chiamare il timer.

L'alternativa sarebbe quella di tornare dalla funzione customEventLoop mentre vengono visualizzati i controlli di sistema e richiamarlo di nuovo quando si riprende l'interfaccia utente personalizzata.

+0

Ho usato i timer per un gioco OpenGL e, nonostante quello che si potrebbe pensare, ho ottenuto i framerate più alti usando questo metodo. Sembra giocare molto meglio con il ciclo degli eventi principale. –

+0

drawnonward, grazie, le modalità ciclo continuo spiegano tutto. Abbiamo anche utilizzato l'approccio basato su NSTimer e ha avuto alcune anomalie con animazioni veloci. In iPhone OS 3.1 c'è CADisplayLink che può aiutare con il problema. –

+0

disegnato, per qualche motivo, non posso contrassegnare la tua risposta come accettata. Questa domanda ha avuto un premio in precedenza, ma hai risposto dopo che la caccia alla taglia si era chiusa e sembra che StackOverflow mi impedisca di contrassegnare la risposta accettata dopo. Strano. –

Problemi correlati