首页 文章

与CGContextDrawImage相比,为什么UIImageView的内存密集程度如此之高

提问于
浏览
5

开发iPad PDF-Reader我们决定准备渲染密集页面的高分辨率图像(其中包含许多路径),并使用这些图像而不是pdf页面来避免性能问题 . 我们认为 3768 by 31024 是可读性和渲染性能之间的良好折衷,导致~1.5 MB的jpeg .

但是,我们测试了两个用于显示图像页面的实现 . 一个使用 CATiledLayer 子类,它也负责处理"normal" PDF页面(使用 CGContextDrawImage 绘图)和另一个使用 UIImageView . 后者的优点是显示和缩放非常快,但内存使用非常糟糕 - 内存大约需要30 MB(这与图像的位图大小一致) . 另一种方法( CATiledLayer )需要更多时间来首次显示页面,并且在缩放后需要另外两秒钟来重新渲染(类似于pdf页面,但速度要快得多)但是不会占用更多内存而不是显示更小的内存图像或PDF页面 .

有谁知道's going on behind the scenes and if it'可以通过使用Quartz Framework将 CGContextDrawImage 的低内存使用与 UIImageView 的高性能结合起来 .

1 回答

  • 4

    不确定这个问题是否仍然相关,但如果是这样,也许这会有所帮助:

    我也在_1315423中与高效显示大型视图的战斗进行了斗争 . 这个问题有很多潜在的部分:

    • 正常 UIView ,包括 UIImageView ,似乎总是完全由内存支持其图像 . 即使您实现 drawRect: 方法,它似乎总是传递视图的整个边界,而不仅仅是滚动视图中可见的区域 . 正如您所发现的,这会快速占用大量内存,因为每个像素占用4个字节 .

    • CATiledLayer 仅请求可见切片的内容 . 它还会丢弃不再可见的磁贴 - 这是节省内存的地方 . 但是,它会在后台线程上进行通知和绘图,同时从白色动画到内容 . 它似乎通过私有API来做到这一点,我还没有找到一种方法来重新实现 CATiledLayer 的功能作为我自己的 CALayer 的子类,因为似乎没有任何通知机制可以作为凡人使用 .

    • 如果您在滚动视图中有多个视图,它们会在页面调入时正确接收 drawRect: 消息 . 但是UIKit似乎很难在视图下方查看过多的子视图 .

    对你而言,我可以看到几个可能的选择:

    • 有可能挽救基于 CATiledLayer 的实施 . fadeDuration 默认为0.25秒,如果加载时间很短,则可能太长 . 你可以将它放到像 1.0/60.0 这样的东西,即一帧 . 从您的描述中不清楚的一件事是您的图像是覆盖整个页面大小还是仅覆盖每个256x256像素的图块 . 对每个图块一遍又一遍地解码整个JPEG将比解码单个图块文件慢得多 .

    • 如果从 CATiledLayer 线程执行所有操作的延迟太高,您可以手动创建一堆切片作为 UIImageView 子视图到空白 UIView ,这是滚动视图的主要子视图 . 这些子视图中的每一个都被分配了自己的图块图像 . 如果你很幸运,UIKit将足够聪明地删除这些视图的内容并按需重新加载相应的JPEG .

    • 如果UIImageViews不够智能,或者您有太多的视图无法应对UIKit,您可以构建自己的视图,在 drawRect: 中加载其JPEG . 如果它是's still too jerky, try with your own CALayers, which will be sublayers of your single view'的空白图层并再次按需加载其图像 . 这是我最终用于平铺图像视图的内容 .

    这应该包括滚动,但如果允许用户缩小(缩小),它仍然可能非常慢 . 在这种情况下,我建议您存储适当的低分辨率版本,并在那些最外面的缩放级别加载/显示那些 .

相关问题