【问题标题】:Rendering a preview of a UIView in another UIView在另一个 UIView 中渲染 UIView 的预览
【发布时间】:2013-07-30 18:05:32
【问题描述】:

我有一个非常有趣的障碍要克服。我正在尝试在另一个单独的 UIView 中显示 UIView 的实时内容。

我要完成的工作与 Mac OS X 中的 Mission Control 非常相似。在 Mission Control 中,中心有大视图,显示桌面或应用程序。除此之外,还有一些可以重组的小视图。这些小视图显示其相应应用程序的实时预览。预览是即时的,帧率是准确的。最终,我试图以尽可能低的成本重现这种效果。

我尝试了许多可能的解决方案,here 显示的解决方案与我得到的一样接近。它可以工作,但是 - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx 方法不会在每次更改时调用。我的解决方案是使用 CADisplayLink 调用 [cloneView setNeedsDisplay],因此在每次屏幕刷新时都会调用它。它非常接近我的目标,但帧速率极低。我认为[CALayer renderInContext:] 太慢了。

如果可以让两个 CALayer 渲染同一个源,那将是非常好的。但是,我不确定如何解决这个问题。幸运的是,这只是一个概念应用程序,并不适用于 App Store,因此我可以使用私有 API。我研究了 IOSurface 和 Quartz 上下文,但到目前为止我还没有解决这个难题。任何意见将不胜感激!

【问题讨论】:

  • 您是否有理由不能使用与更新原始文件相同的方法来复制视图和更新两者?
  • 是的,有。每个视图都非常复杂,复制一个会占用大量内存和时间。一个更实用和有效的解决方案是简单地预览它。 OS X 完美地做到了,所以它一定是可能的。
  • Mission Control 实现可能正在使用用于 OSX 的私有未记录 API。这些 API 在 iOS 上可能不可用。 OSX 也可以在 Mac 上以更高的速度渲染 InContext,而 iOS 看起来很滞后。
  • 虽然这是真的,但正如我所说,我可以完全访问 iOS 中使用的所有私有 API,其中包括 OS X 上使用的几乎所有 API。该功能很可能在某处可用。 iOS 比大多数人认为的要强大得多,我相信这是可能的。我只需要朝着正确的方向轻推。虽然 renderInContext 在 OS X 上明显更快,但我怀疑 OS X 是否使用 renderInContext。必须有其他解决方案。

标签: iphone objective-c cocoa-touch uikit quartz-core


【解决方案1】:

iOS 和 OSX 实际上在底层基本相同。 (然而,当你获得更高的堆栈时,iOS 实际上比 OSX 更先进,因为它更新并且有一个新的开始)

但是,在这种情况下,它们都使用相同的东西(我相信)。您会注意到有关任务控制的一些信息。它隔离了“窗口”而不是视图。在 iOS 上,每个 UIWindow 都有一个“.contentID”属性,CALayerHost 可以用来使渲染服务器在它们之间共享渲染上下文(即 2 层)。

所以我的建议是让您的视图独立于 UIWindows 并免费获得本机镜像(ish)。 (根据我的经验,CALayerHost 使用渲染服务器接管目标图层位置,因此如果 CALayerHost 和窗口都可见,则窗口将不再存在,只有图层主机(在 OSX 上使用它们的方式) iOS 不是问题)。)

因此,如果您要进行真正的镜像,复制 2 个副本,您将需要求助于您正在考虑的那种事情。

1 选项是创建一个 UIView 子类,它使用 https://github.com/yyfrankyy/iOS5.1-Framework-Headers/blob/master/UIKit.framework/UIView-Rendering.h#L12 这个 UIView 私有方法获取目标视图的 IOSurface,然后每秒使用一次 CADisplayLink 获取并绘制表面。

另一个可能有效的选项(我不确定,因为我不知道您的设置或所需的效果)可能只是使用 CAReplicatorLayer,它使用相同的后备存储显示 CALayer 的镜像(非常快速和高效+ 公共稳定 API)。

抱歉,我无法给您一个固定的“这就是答案”,但希望我已经为您提供了足够的想法和可能性来开始。 我还提供了一些链接,这些链接指向您可能会觉得有用的内容。

What's the magic behind CAReplicatorLayer?

http://aptogo.co.uk/2011/08/no-fuss-reflections/

http://iphonedevwiki.net/index.php/SBAppContextHostManager

http://iphonedevwiki.net/index.php/SBAppContextHostView

http://iphonedevwiki.net/index.php/CALayerHost

http://iky1e.tumblr.com/post/33109276151/recreating-remote-views-ios5

http://iky1e.tumblr.com/post/14886675036/current-projects-understanding-ios-app-rendering

【讨论】:

  • 完美,正是我想要的,只是朝着正确的方向轻推。我确实有一个问题;当你说每个窗口都有一个 .contentID 属性时,你的意思是一个 ._contextId 属性吗?我假设是这样。这是我之前尝试过的,使用 CALayerHosts,但是我发现作为另一个 UIWindow 的子视图的 UIWindow 的上下文 ID 具有相同的上下文 ID。我想我已经找到了发生这种情况的原因,并且我应该能够使某些工作正常进行。这是非常有价值的信息!你做了非常了不起的工作。
  • UIWindows 不应该是其他 UIWindows 的子视图。 UIWindow 是包含 UIView 的容器,它们没有超级视图。如果您将它们添加到其他窗口,那么是的,它们将具有相同的 contextID,因为只有它们的父级实际上有一个,并且它只会报告这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-14
  • 2019-04-14
  • 1970-01-01
  • 2014-09-15
  • 2015-05-17
  • 2012-01-25
相关资源
最近更新 更多