iOS OpenGL Catch-22:App Switcher

时间:2016-06-02 21:04:02

标签: ios objective-c ipad opengl-es layoutsubviews

与许多开发人员一样,我有一个应用程序通过UIView子类使用OpenGL,layerClass:方法返回[CAEAGLLayer class]

注意我使用GLKitGLKViewGLKViewController

当我点击“主页”将应用置于后台时,在applicationDidEnterBackground之后,iOS调用我的视图layoutSubviews两次,使用纵向和横向尺寸,尝试生成“应用快照”,如此处所述(请参阅“准备应用程序快照”):

https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/StrategiesforHandlingAppStateTransitions/StrategiesforHandlingAppStateTransitions.html#//apple_ref/doc/uid/TP40007072-CH8-SW10

这怎么可能有效?

此页面上的非常明确的建议似乎存在直接矛盾(请参阅“后台应用程序可能无法在图形硬件上执行命令”):

https://developer.apple.com/library/ios/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/ImplementingaMultitasking-awareOpenGLESApplication/ImplementingaMultitasking-awareOpenGLESApplication.html#//apple_ref/doc/uid/TP40008793-CH5-SW1

我们不能在applicationDidEnterBackground

之后用OpenGL绘制任何内容

如果我们不绘制,我们就无法生成快照。我们必须违反一条规则或另一条规则。

但我们也希望在两个方向都有很好的快照,这样当用户双击主页并转到App Switcher时,他们会看到合理的快照图像。

即使我通过创建OpenGL表面和绘图(与Apple dox相反,不会崩溃)暂时更改我的代码以完全实现layoutSubviews之后的applicationDidEnterBackground,然后我加倍 - 单击主页并以不同方向查看快照,只有我之前所处方向的快照是正确的。另一个是另一个快照的超级丑陋的重新缩放。 Apple似乎正在经历拍摄快照的动作,但实际上并没有拍摄它们。

我在iPad Mini上看到iOS 9.3.2上的这种行为。该行为未在大多数/所有iPhone设备上显示,因为它们不支持横向App Switcher。

更新:问题也会发生,并且更糟糕的是,当使用新的iOS 9“幻灯片”多任务处理功能并在正常的全屏应用和应用之间切换相同的应用时滑过另一个应用程序。 iOS似乎只捕获最后一个应用程序大小的快照,所以在使用640px宽的应用程序然后尝试使用App Switcher进入应用程序全屏后,我们在应用程序中看到一个奇怪的像素超出比例的快照切换器也在发射的第一秒。必须有一些方法来解决这个问题!

更新2 :我看过一些iOS应用,我知道它们只是OpenGL应用,如果你以纵向方式使用它们,那么回到Home并旋转到横向,然后加倍-click Home,你会看到肖像发布图像,而不是像我看到的那样可怕,扭曲,不对称的图像。虽然我更喜欢渲染快照图像,但我甚至很乐意看到启动图像。但是每个人都提到的选项ignoreSnapshotOnNextApplicationLaunch不起作用,因为它只会影响您在实际应用启动时看到的内容,而不会影响双击Home时在App Switcher中看到的内容,对于StackOverflow上的许多人来说,它实际上甚至都没有工作(甚至在发布时也没有)。

我们如何解决这个Catch-22?

这个StackOverflow线程(与我不同,OP在这里使用GLKit,但症状是相同的):

iOS OpenGL ES screen rotation while background apps bar visible

确认iOS 上的某些OpenGL应用能够在Home双按应用切换器中为两个方向都拥有正确的预览图像。他们是怎么做到的?

如何在App Switcher中以两个方向显示正确的快照?

以下是我单击“主页”按钮一次时来自iOS的AppDelegate(appdel),ViewController(eaglc)和View(eaglv)调用的日志退出应用程序。您可以在didEnterBackground之后看到快照的尝试:

+  189.57ms      appdel appWillResignActive
+    0.74ms        appdel appWillResignActive between_view_os_callbacks 0
+    4.11ms        appdel appWillResignActive between_view_os_callbacks 0 done
+    0.82ms        appdel appWillResignActive activation_changed
+    1.50ms        appdel appWillResignActive activation_changed done
+    0.47ms        appdel appWillResignActive between_view_os_callbacks 1
+    2.68ms          drawing rect [(144,1418)+(2,66)] (0 left)
+   44.28ms          swap_buffers glFlush()
+    6.16ms          swap_buffers presentRenderBuffer
+    9.01ms        appdel appWillResignActive between_view_os_callbacks 1 done
+    0.61ms        appdel save_state
                     ..app saving data, no OpenGL here..
+    0.49ms          appdel save_state calling glFinish
+    0.34ms        appdel save_state done
+    0.25ms      appdel appWillResignActive done
+  492.72ms      appdel applicationDidEnterBackground
+    0.56ms        appdel save_state
                     ..app saving data, no OpenGL here..
+    0.65ms          appdel save_state calling glFinish
+    0.54ms        appdel save_state done
+    0.65ms        eaglv let_go_of_frame_buffer_render_buffer
                     app drops OpenGL frame_buffer and render_buffer here
+    1.10ms      appdel applicationDidEnterBackground done

Now we are not supposed to do OpenGL, BUT...

+    6.30ms      eaglc supportedInterfaceOrientations
+    5.74ms      about_to_sleep between_view_os_callbacks
+    1.30ms        SKIPPING between_view_os_callbacks cuz app in background
+    0.66ms      about_to_sleep between_view_os_callbacks done
+  135.85ms      eaglc willRotateToInterfaceOrientation
+    2.49ms      appdel willChangeStatusBarFrame new=0,0 768x20
+    3.21ms      appdel didChangeStatusBarFrame old=0,0 1024x20

we get a portrait layoutSubviews....

+    1.26ms      eaglv layoutSubviews (initted=1, have_fbrb=0)
+    1.80ms        eaglv assure_frame_buffer_render_buffer
+    0.95ms          eaglv assure_fbrb scale ios=2 eaglv=2
+    0.90ms          eaglv assure_fbrb (frame=1536,2048)
+    1.04ms          eaglv assure_fbrb (layer frame=1536,2048)
+    0.92ms        eaglv assure_fbrb in bg: will make fbrb later
+    0.96ms      eaglv layoutSubviews done
+    3.11ms      eaglc didRotateFromInterfaceOrientation
+  149.07ms      eaglc willRotateToInterfaceOrientation
+    1.99ms      appdel willChangeStatusBarFrame new=0,0 1024x20
+    2.35ms      appdel didChangeStatusBarFrame old=0,0 768x20

then a landscape layoutSubviews...

+    1.91ms      eaglv layoutSubviews (initted=1, have_fbrb=0)
+    1.09ms        eaglv assure_frame_buffer_render_buffer
+    0.91ms          eaglv assure_fbrb scale ios=2 eaglv=2
+    1.65ms          eaglv assure_fbrb (frame=2048,1536)
+    0.92ms          eaglv assure_fbrb (layer frame=2048,1536)
+    0.93ms        eaglv assure_fbrb in bg: will make fbrb later
+    0.83ms      eaglv layoutSubviews done
+    2.79ms      eaglc didRotateFromInterfaceOrientation

and, adding insult to injury, we get this log message:

Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before snapshotting or snapshot after screen updates.

0 个答案:

没有答案