【问题标题】:Modifying UIVIew above GLKView causing crashes修改 GLKView 上方的 UIVIew 导致崩溃
【发布时间】:2017-04-24 16:42:44
【问题描述】:

我的应用程序发生随机崩溃。最终我发现当我添加 UIVIew 元素并修改它们的中心位置时会发生崩溃。 IPad Air 2 上不会发生崩溃,但 IPad Air 上的情况是一致的 - 当 UIViews 打开时,会发生崩溃,并且当视图被移除时崩溃会消失。崩溃与以下堆栈异步发生:

#0  0x0000000190bf1f28 in gpus_ReturnGuiltyForHardwareRestart ()
#1  0x0000000190bf2ec4 in gpusSubmitDataBuffers ()
#2  0x0000000189d56254 in gliPresentViewES_Exec ()
#3  0x0000000189d5616c in gliPresentViewES ()
#4  0x0000000189d63cbc in -[EAGLContext presentRenderbuffer:] ()
#5  0x0000000101ff8078 in EAGLContext_presentRenderbuffer(EAGLContext*, objc_selector*, unsigned long) ()
#6  0x00000001877dc638 in -[GLKView _display:] ()
#7  0x000000018b55eeb8 in CA::Layer::display() ()
#8  0x000000018b5413a0 in CA::Layer::display_if_needed(CA::Transaction*) ()
#9  0x000000018b54108c in CA::Layer::layout_and_display_if_needed(CA::Transaction*) ()
#10 0x000000018b54071c in CA::Context::commit_transaction(CA::Transaction*) ()
#11 0x000000018b540470 in CA::Transaction::commit() ()
#12 0x000000018b539c10 in CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) ()
#13 0x000000018666f3f8 in __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ ()
#14 0x000000018666d19c in __CFRunLoopDoObservers ()
#15 0x000000018666d5cc in __CFRunLoopRun ()
#16 0x000000018659d280 in CFRunLoopRunSpecific ()
#17 0x00000001915500cc in GSEventRunModal ()
#18 0x000000018bd8adf8 in UIApplicationMain ()
#19 0x000000010077d36c in main at /Code/splinedr/Splinedr/main.mm:18
#20 0x000000019b7fa8b8 in start ()

我使用对[self.view needDisplay] 的调用来渲染 OpenGL,并在此之前修改 UIViews。

我应该如何处理这个问题?

【问题讨论】:

  • 只有在添加 UIIMageViews 时才会发生崩溃吗? GLKView 是如何刷新的?你是直接调用display吗?如果是这样,您是否将 enableSetNeedsDisplay 设置为 0?
  • 我编辑了我的问题并添加了更多信息
  • 您是否将 GLKView 的 paused 属性设置为 0?
  • 是的 - 但我确实在短时间内多次调用需要显示,因为视图发生变化(用户如果改变视角)
  • 在添加 UIImageViews 的那一刻发生吗?

标签: ios opengl-es opengl-es-2.0 glkview


【解决方案1】:

确保您的 GLKViewController 已暂停,并且 GLKView 的 enableSetNeedsDisplay 设置为 1。如果这些设置已正确,则可能是您正在后台线程上调用 setNeedsDisplay,并且您的子视图正在触发冲突调用主线程。确保您对 setNeedsDisplay 的所有调用都是从主线程调用的。一种简单的验证方法是在每个调用旁边放置一个打印语句。

[self.view setNeedsDisplay];
printf("%s\n",dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)); 

另一种选择是将 enableSetNeedsDisplay 设置为零,然后直接调用 [self.view display]。当视图出现和框架发生变化时,您可能需要在这里和那里添加几个显示调用,但它最终会给您更多的控制权。如果它不能完全解决问题,它至少会使跟踪堆栈跟踪变得更容易,因为所有绘图调用都源自您对显示的调用之一。

【讨论】:

  • 这是我的第一个猜测。 setNeedsDisplay 仅在主线程上调用
【解决方案2】:

Apple 表示异常表明存在一些后台滥用,并强烈建议进入后台的应用暂停或停止使用 OpenGL ES。

Apple Documentation for Implementing a Multitasking-Aware OpenGL ES App

【讨论】:

    猜你喜欢
    • 2018-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多