是否使用drawRect(什么时候应该使用drawRect/Core Graphics vs 子视图/图像,为什么?)

2024-03-10

为了澄清这个问题的目的:我知道如何使用子视图和使用drawRect创建复杂的视图。我试图完全理解何时以及为何使用其中一种而不是另一种。

我也明白提前优化那么多并在进行任何分析之前以更困难的方式做一些事情是没有意义的。考虑到我对这两种方法都很满意,现在真的想要更深入的了解。

我的很多困惑来自于学习如何使表格视图滚动性能真正平滑和快速。当然这个方法的原始出处是来自推特背后的作者 http://atebits.tumblr.com/post/197580827/fast-scrolling-in-tweetie-with-uitableview适用于 iPhone(以前称为 tweetie)。基本上它说,要使表格滚动平滑,秘诀是不使用子视图,而是在一个自定义 uiview 中完成所有绘图。从本质上讲,使用大量子视图似乎会减慢渲染速度,因为它们有大量开销,并且不断在其父视图上重新合成。

公平地说,这篇文章是在 3GS 刚刚诞生的时候写的,而且从那时起,iDevices 的速度已经快得多了。仍然这个方法 http://engineering.twitter.com/2012/02/simple-strategies-for-smooth-animation.html is 经常 http://volonbolon.net/post/634453483/optimizing-table-views-for-performance 建议 http://blog.giorgiocalderolla.com/2011/04/16/customizing-uitableviewcells-a-better-way/#comment-208 on the 互联网络 http://nachbaur.com/blog/core-graphics-isnt-scary-honest以及其他高性能表。事实上这是一个建议的方法Apple 的表示例代码 http://developer.apple.com/library/ios/#samplecode/TableViewSuite/Listings/5_CustomTableViewCell_Classes_TimeZoneView_m.html#//apple_ref/doc/uid/DTS40007318-5_CustomTableViewCell_Classes_TimeZoneView_m-DontLinkElementID_42,已在多个 WWDC 视频中得到建议(iOS 开发者实用绘图 https://developer.apple.com/videos/wwdc/2011/?id=129),以及许多iOS编程书籍 https://rads.stackoverflow.com/amzn/click/com/B00AJPDJMC.

甚至还有看起来很棒的工具 http://www.paintcodeapp.com设计图形并为其生成 Core Graphics 代码。

所以一开始我相信“Core Graphics 存在是有原因的。它很快!”

但一旦我想到“尽可能选择核心显卡”,我就开始发现,drawRect 通常会导致应用程序的响应速度很差,而且内存非常昂贵,并且确实会增加 CPU 的负担。基本上,我应该“避免重写drawRect http://screencast.com/t/jVbYIKiI“(2012 年全球开发者大会iOS 应用程序性能:图形和动画 https://developer.apple.com/videos/wwdc/2012/?id=238)

所以我想,就像所有事情一样,它很复杂。也许您可以帮助我自己和其他人理解何时以及为什么使用drawRect?

我看到一些使用 Core Graphics 的明显情况:

  1. 您有动态数据(Apple 的股票图表示例)
  2. 您有一个灵活的 UI 元素,无法使用简单的可调整大小的图像来执行
  3. 您正在创建一个动态图形,一旦渲染就会在多个地方使用

我看到了避免使用核心显卡的情况:

  1. 视图的属性需要单独设置动画
  2. 您的视图层次结构相对较小,因此任何使用 CG 的额外努力都是不值得的
  3. 您想要更新视图的各个部分而不重新绘制整个视图
  4. 当父视图大小发生变化时,子视图的布局需要更新

所以赐予你的知识。在什么情况下你会使用drawRect/Core Graphics(也可以通过子视图来完成)?哪些因素导致您做出这个决定?如何/为什么建议在一个自定义视图中进行绘制以实现黄油般平滑的表格单元格滚动,但出于性能原因,Apple 建议不要使用drawRect?简单的背景图像怎么样(什么时候使用 CG 创建它们,什么时候使用可调整大小的 png 图像)?

制作有价值的应用程序可能不需要对这个主题有深入的了解,但我不喜欢在无法解释原因的情况下在技术之间进行选择。我的大脑对我很生气。

问题更新

谢谢大家的信息。这里需要澄清一些问题:

  1. 如果您正在使用核心图形绘制某些内容,但可以使用 UIImageViews 和预渲染的 png 完成相同的操作,那么您应该始终走这条路吗?
  2. 类似的问题:尤其是像这样的坏工具 http://www.paintcodeapp.com,什么时候应该考虑在核心图形中绘制界面元素? (可能当你的元素的显示是可变的。例如,一个按钮有 20 种不同的颜色变化。还有其他情况吗?)
  3. 根据我在下面的回答中的理解,通过在复杂的 UIView 渲染本身之后有效捕获单元格的快照位图,并在滚动和隐藏复杂视图时显示它,是否可以为表格单元格获得相同的性能增益?显然,有些部分必须解决。只是我有一个有趣的想法。

尽可能坚持使用 UIKit 和子视图。您可以提高工作效率,并利用所有 OO 机制,使事情更容易维护。当您无法从 UIKit 中获得所需的性能时,或者您知道尝试在 UIKit 中组合绘图效果会更加复杂时,请使用 Core Graphics。

一般工作流程应该是构建带有子视图的表视图。使用 Instruments 测量应用程序支持的最旧硬件上的帧速率。如果您无法获得 60fps,请下拉至 CoreGraphics。当你这样做了一段时间后,你就会意识到 UIKit 何时可能是浪费时间。

那么,为什么 Core Graphics 速度快呢?

CoreGraphics 并不是很快。如果一直使用它,你的速度可能会很慢。它是一个丰富的绘图 API,需要在 CPU 上完成工作,而不是卸载到 GPU 的大量 UIKit 工作。如果您必须制作一个球在屏幕上移动的动画,那么每秒在视图上调用 setNeedsDisplay 60 次将是一个糟糕的主意。因此,如果视图的子组件需要单独进行动画处理,则每个组件都应该是一个单独的层。

另一个问题是,当你不使用drawRect进行自定义绘图时,UIKit可以优化库存视图,因此drawRect是一个无操作,或者它可以采取合成的快捷方式。当你重写drawRect时,UIKit必须采取慢速路径,因为它不知道你在做什么。

对于表视图单元格来说,这两个问题可能会被它的好处所抵消。当视图首次出现在屏幕上时调用drawRect后,内容将被缓存,并且滚动是由GPU执行的简单转换。因为您处理的是单个视图,而不是复杂的层次结构,所以 UIKit 的 drawRect 优化变得不那么重要。因此,瓶颈就变成了你可以在多大程度上优化你的 Core Graphics 绘图。

只要有可能,就使用 UIKit。做最简单、有效的实现。轮廓。当有激励时,进行优化。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否使用drawRect(什么时候应该使用drawRect/Core Graphics vs 子视图/图像,为什么?) 的相关文章

随机推荐