我正在编写一个Cocoa OpenGL应用程序,并在每个this technical note中使用CVDisplayLink运行主循环。它可以很好地运行循环。

问题是有时退出应用程序后,我的显示链接回调将在其自己的线程上被调用。这将导致我的渲染代码在调用任何OpenGL函数(在本例中为glClear)时立即被调用并崩溃,因为我的上下文不再存在。

我在NSView的CVDisplayLinkRelease(displayLink);函数中包含dealloc,但是由于ARC,它似乎从未被调用。有什么办法可以确保在查看之前销毁我的显示链接吗?

编辑:我没有注意到崩溃实际上是由我的一个断言触发的。在每次进行OpenGL调用后,我在glGetError上声明以确保可以尽早发现错误。调用glClear[[view openGLContext] flushBuffer];后,出现错误1286,即GL_INVALID_FRAMEBUFFER_OPERATION

这是合乎逻辑的,因为我的窗口和视图都被重新分配了,但这对解决问题没有帮助。我不想忽略这些错误,因为它们显然可能会发生的不仅仅是这种情况。我仍然需要找到“正确”的方法来确保在查看之前关闭我的显示链接。

最佳答案

当应用程序终止时,其自动释放池中的任何内容都不会释放-该应用程序仅exit s并让操作系统清理内存。由于没有释放任何内容,因此没有任何内容收到dealloc消息。

这意味着两件事:


您不应将文件,连接或并非仅驻留在内存中的任何其他内容的生存期与对象的生存期联系起来。
您应确保根据终止和解除分配来终止这些事务的生命周期。


有两种处理终止的方法。我通常在单窗口应用程序中执行此操作的方法是,让我的应用程序的委托没有别的,直接拥有我的主窗口控制器。另一种方法是将您自己添加为NSApplicationWillTerminate通知的观察者,并通过例如停止显示链接来响应它。

如果清理的任何部分可能需要一些时间,则应用程序的委托应通过返回applicationShouldTerminate:来响应NSTerminateLater,并且在完成所需的操作后,应向应用程序发送replyToApplicationShouldTerminate:消息。

另一个解决原始问题的方法(在您有机会关闭链接之前调用CVDisplayLink回调)完全相反:启用sudden termination。启用该功能后,您的应用程序将通过发送自己的SIGKILL(最好由命令行调用kill -9知道)来退出,这意味着您的每个线程都将立即停止。

当然,如果您确实需要清理任何东西(锁定文件,网络连接等),则应在这些设备的生命周期内禁用其突然终止,并准备在此期间进行常规终止。

关于cocoa - 正确关闭CVDisplayLink,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11251913/

10-10 16:31