Kennt jemand oder haben gute Verbindungen, die erklären, was iPhone-Ereignisschleife unter der Haube tut?Benutzerdefinierte Ereignisschleife und UIKit-Steuerelemente. Welche zusätzliche Magie hat Apples Event-Loop?
Wir verwenden eine benutzerdefinierte Ereignisschleife in unserem OpenGL-basierten iPhone-Spielframework. Er ruft unser Spiel-Rendering-System auf, ruft presentRenderbuffer auf und pumpt Events mit CFRunLoopRunInMode. Weitere Informationen finden Sie im folgenden Code.
Es funktioniert gut, wenn wir nicht UIKit Kontrollen verwenden (als Beweis, versuchen Facetap, unser erstes veröffentlichtes Spiel).
Allerdings, wenn UIKit steuert, alles fast funktioniert, aber nicht ganz. Insbesondere funktioniert das Scrollen von UIKit-Steuerelementen nicht ordnungsgemäß.
Betrachten wir zum Beispiel folgendes Szenario.
- Wir zeigen UIImagePickerController über unsere eigene Ansicht.
- UIImagePickerController deckt unsere benutzerdefinierte Ansicht ab
- Wir pausieren auch unser eigenes Rendering, verwenden aber weiterhin die benutzerdefinierte Ereignisschleife.
Wie gesagt, alles funktioniert, außer Scrollen.
- Kommissionieren von Fotos funktioniert.
- Drilling nach Fotoalben funktioniert und Übergangsanimationen sind glatt.
- Beim Versuch, die Albumansicht zu scrollen, folgt die Ansicht Ihrem Finger.
Problem: Beim Scrollen stoppt das Scrollen sofort, nachdem Sie Ihren Finger gehoben haben. In der Regel wird die Verarbeitung basierend auf der Geschwindigkeit Ihrer Bewegung reibungslos fortgesetzt, jedoch nicht, wenn die benutzerdefinierte Ereignisschleife verwendet wird. Es scheint, dass die Ereignisschleife des iPhones mit dem UIKit-Scrollen etwas magisch macht, das wir selbst nicht implementiert haben.
Jetzt können wir UIKit-Steuerelemente zusammen mit unserem eigenen System gut funktionieren, indem wir Apples Ereignisschleife verwenden und unser eigenes Rendering über NSTimer-Callbacks aufrufen. Ich würde jedoch gerne verstehen, was möglicherweise in der Ereignisschleife des iPhones passiert, die nicht in unserer benutzerdefinierten Ereignisschleife implementiert ist.
- (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;
}
}
}
Ich habe Timer für ein OpenGL-Spiel verwendet und trotz allem, was Sie zuerst denken, habe ich die höchsten Frameraten mit dieser Methode. Es scheint einfach viel besser mit der Hauptereignisschleife zu spielen. –
Drawnonward, danke, run loop Modi erklärt alles. Wir haben auch NSTimer basierten Ansatz verwendet und es hatte bestimmte Anomalien mit schnellen Animationen. In iPhone OS 3.1 gibt es CADisplayLink, das bei dem Problem helfen könnte. –
gezeichnet, aus irgendeinem Grund kann ich Ihre Antwort nicht als akzeptiert markieren. Diese Frage hatte früher ein Kopfgeld, aber Sie haben geantwortet, nachdem die Kopfgeldjagd geschlossen wurde und es scheint, dass Stackoverflow verhindert, dass ich die Antwort danach akzeptiere. Seltsam. –