gpt4 book ai didi

iphone - 自定义事件循环和 UIKit 控件。苹果的事件循环有什么额外的魔力?

转载 作者:行者123 更新时间:2023-12-03 18:33:12 25 4
gpt4 key购买 nike

有人知道或有好的链接来解释 iPhone 的事件循环在幕后的作用吗?

我们在基于 OpenGL 的 iPhone 游戏框架中使用自定义事件循环。它调用我们的游戏渲染系统,调用presentRenderbuffer并使用CFRunLoopRunInMode泵送事件。详情请参阅下面的代码。

当我们不使用 UIKit 控件时,它效果很好(作为证明,请尝试 Facetap,我们的第一个发布的游戏)。

但是,当使用 UIKit 控件时,一切几乎都能工作,但又不完全有效。具体来说,UIKit 控件的滚动无法正常工作。

例如,让我们考虑以下场景。

  • 我们在自己的 View 之上显示 UIImagePickerController。
  • UIImagePickerController 覆盖了我们的自定义 View
  • 我们还暂停了自己的渲染,但继续使用自定义事件循环。

如上所述,除了滚动之外,一切正常。

  • 挑选照片很有效。
  • 深入查看相册作品和过渡动画非常流畅。
  • 尝试滚动相册 View 时, View 会跟随您的手指移动。

问题:滚动时,松开手指后滚动立即停止。通常,它会根据您的移动速度平稳地继续,但当我们使用自定义事件循环时则不然。看起来 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;
}
}
}

最佳答案

如果您在 [UIScrollView isDecelerating] 时从 [UIScrollView setContentOffset:]NSLog [[NSRunLoop currentRunLoop] currentMode] code> 为 true,您将看到 UITrackingRunLoopMode

一般来说,系统会在主 UI 线程运行循环上使用除 kCFRunLoopDefaultMode 之外的模式,仅记录了其中的一些模式。获得完整系统行为的唯一方法是与主线程上的系统运行循环配合。

您可以尝试使用NSTimer并让系统调用您,而不是自己调用CFRunLoopRunInModeNSTimer 可以随时间自由运行,并且当没有显示其他 UI 时,系统运行循环除了调用计时器之外不会执行任何操作。

另一种方法是在显示系统控件时从 customEventLoop 函数返回,并在恢复自定义 UI 时再次调用它。

关于iphone - 自定义事件循环和 UIKit 控件。苹果的事件循环有什么额外的魔力?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2592427/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com