有谁知道或有很好的链接来解释 iPhone 的事件循环在幕后做什么?
我们在基于 OpenGL 的 iPhone 游戏框架中使用自定义事件循环。它调用我们的游戏渲染系统,调用 presentRenderbuffer 并使用 CFRunLoopRunInMode 泵送事件。有关详细信息,请参阅下面的代码。
当我们不使用 UIKit 控件时它工作得很好(作为证明,试试Facetap,我们第一个发布的游戏)。
然而,当使用 UIKit 控件时,几乎一切都可以正常工作,但并不完全正常。具体来说,UIKit 控件的滚动无法正常工作。
例如,让我们考虑以下场景。
- 我们在自己的视图之上显示 UIImagePickerController。
- UIImagePickerController 覆盖了我们的自定义视图
- 我们也暂停了自己的渲染,但继续使用自定义事件循环。
如前所述,一切正常,除了滚动。
- 挑选照片工作。
- 深入到相册作品和过渡动画很流畅。
- 尝试滚动相册视图时,视图会跟随您的手指。
问题:滚动时,抬起手指后滚动立即停止。通常,它会根据您的移动速度平稳地继续,但当我们使用自定义事件循环时则不会。似乎 iPhone 的事件循环正在做一些我们自己没有实现的与 UIKit 滚动相关的魔法。
现在,通过使用 Apple 的事件循环并通过 NSTimer 回调调用我们自己的渲染,我们可以让 UIKit 控件与我们自己的系统一起正常工作。但是,我仍然想了解,在我们的自定义事件循环中未实现的 iPhone 事件循环中可能发生的事情。
- (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;
}
}
}