【发布时间】:2011-10-07 15:00:48
【问题描述】:
我知道,我不是第一个尝试在 OSX 上将 Cocoa 与现有的 c/c++ 主循环一起使用的人,但我并不是很喜欢迄今为止遇到的解决方案,所以我想出了一个不同的解决方案我想讨论的想法。我发现(在 glut、glfw、SDL 以及我认为的 QT 中)最常见的方法是使用轮询来替换 NSApplications 运行方法并自己处理事件:
nextEventMatchingMask:untilDate:inMode:dequeue:
这有一个很大的缺点是 CPU 永远不会真正空闲,因为你必须一直轮询以检查是否有任何新事件,而且它不是 NSApplications 运行函数中唯一发生的事情,所以它可能会破坏一些如果您使用此替换,请详细说明。
所以我想做的是保持可可 runLoop 完好无损。想象一下,您将在 c++ 中实现自己的计时器方法,这些方法通常会在您的主循环中进行管理和触发(这只是一个示例)。我的想法是将所有循环部分移动到辅助线程(因为据我所知,需要从主线程调用 NSApplication 运行),然后将自定义事件发布到我的 NSApplication 派生版本,该版本在其内部适当地处理它们发送事件:方法。例如,如果我的 c++ 循环中测量的计时器触发,我会向 NSApplication 发布一个自定义事件,该事件反过来运行我的应用程序的 loopFunc() 函数(也位于主线程中),该函数会适当地将事件发送到我的 c++ 事件链中. 首先,您认为这是一个好的解决方案吗? 如果是,你将如何在可可中实现它,我只在 NSEvent Reference 中找到了这个方法来发布自定义 NSApplicationDefined 事件:
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 中发布和检查自定义事件的方式吗?您认为这是一种无需轮询即可将可可集成到现有运行循环中的有效方法吗?
【问题讨论】:
-
嗨,以防万一有人想知道我如何解决这个问题:我在派生的 NSApplication 类 sendEvent 函数中获取所有相关事件并将它们转发到我的事件循环。如果我需要我的事件循环运行,我通过 performSelectorOnMainThread 通知 NSApplication,类似于:[theAppNotifier performSelectorOnMainThread:@selector(runMyMainLoop) withObject:nil waitUntilDone:NO];这对我来说是一个很好的解决方案,因为我不必侵入可可主循环。相反,我让它自己运行。
标签: c++ cocoa integration nsapplication