我知道,我不是第一个尝试在 OSX 上将 Cocoa 与现有的 c/c++ 主循环一起使用的人,但我不太喜欢目前遇到的解决方案,所以我想出了一个不同的想法想讨论。我发现(在 glut、glfw、SDL 以及我认为的 QT 中)最常见的方法是使用轮询来替换 NSApplications 运行方法并自己处理事件:
nextEventMatchingMask:untilDate:inMode:dequeue:
这有一个很大的缺点,即 cpu 永远不会真正空闲,因为您必须一直轮询以检查是否有任何新事件,而且它不是 NSApplications 运行函数中唯一发生的事情,因此如果您可能会破坏一些细节使用这个替代品。
所以我想做的是保持可可 runLoop 完好无损。想象一下,您将在 c++ 中实现自己的计时器方法,这些方法通常会在您的主循环中进行管理和触发(这只是一个示例)。我的想法是将所有循环部分移动到辅助线程(因为据我所知,需要从主线程调用 NSApplication 运行),然后将自定义事件发布到我的 NSApplication 派生版本,该版本在其内部适当地处理它们发送事件:方法。例如,如果我的 c++ 循环中测量的计时器触发,我会向 NSApplication 发布一个自定义事件,该事件反过来运行我的应用程序的 loopFunc() 函数(也位于主线程中),该函数会适当地将事件发送到我的 c++ 事件链中. 首先,您认为这是一个好的解决方案吗?如果是,
otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:
然后使用类似的东西:
[NSApp postEvent:atStart:]
通知 NSApplication。
我宁愿发布一个没有关于窗口的任何信息的事件(在 otherEventWithType 中),我可以简单地忽略那部分吗?
然后我想像这样覆盖 NSApplications sendEvent 函数:
- (void)sendEvent:(NSEvent *)event
{
//this is my custom event that simply tells NSApplication
//that my app needs an update
if( [event type] == NSApplicationDefined)
{
myCppAppPtr->loopFunc(); //only iterates once
}
//transform cocoa events into my own input events
else if( [event type] == NSLeftMouseDown)
{
...
myCppAppPtr->loopFunc(); //also run the loopFunc to propagate input events
}
...
//dont break the cocoa event chain
[super sendEvent:event];
}
很抱歉这篇长文,但这一直困扰着我,因为到目前为止我对这个主题的发现并不满意。这就是我在 NSApplication 中发布和检查自定义事件的方式吗?您认为这是将可可集成到现有运行循环中而不进行轮询的有效方法吗?