石英2D drawRect法(iPhone)

石英2D drawRect法(iPhone),iphone,ios,cocoa-touch,quartz-graphics,Iphone,Ios,Cocoa Touch,Quartz Graphics,我面前有4本不同的iPhone/Cocoa/Core Animation/Objective-C书籍,还有大量来自网络的示例代码。然而,不知何故,我仍然觉得我缺少了一些基本的理解,即如何在Quartz 2D中进行绘图 drawRect()只是一个执行绘图代码的钩子吗?或者这种方法也应该重新绘制“损坏”的区域,并且需要重新绘制?我可以只画一次我的东西,然后它就“粘住”了吗?或者我必须随时通过drawRect()重新绘制整个场景吗?Java的Graphics2D对象就是这样工作的——每次调用pain

我面前有4本不同的iPhone/Cocoa/Core Animation/Objective-C书籍,还有大量来自网络的示例代码。然而,不知何故,我仍然觉得我缺少了一些基本的理解,即如何在Quartz 2D中进行绘图

drawRect()
只是一个执行绘图代码的钩子吗?或者这种方法也应该重新绘制“损坏”的区域,并且需要重新绘制?我可以只画一次我的东西,然后它就“粘住”了吗?或者我必须随时通过
drawRect()
重新绘制整个场景吗?Java的Graphics2D对象就是这样工作的——每次调用paint()时都必须绘制整个“图像”,因此必须随时准备重新构造(或缓存它)

您将如何实现一个简单的绘图程序?您是否需要“记住”用户绘制的每条线/点/笔划,并在每次调用
drawRect()
时复制这些线/点/笔划?“屏幕外”渲染如何;您可以完成所有绘图,然后调用
[self-setNeedsDisplay]
将写入刷新到屏幕上吗

比方说,为了响应用户的触摸,我想在他触摸的屏幕上放一个“X”。X应该保持在那里,每次新的触摸都会产生另一个X。我是否需要记住所有这些触摸坐标,然后在
drawRect()中绘制它们

编辑:


除非我误解了,否则乔科诺和赫克托·拉莫斯下面的回答是相互矛盾的。这很好地说明了我对这个问题的困惑。:-)

drawRect()将绘制到屏幕外缓冲区。你不需要在任何时候重新绘制区域被“破坏”的部分,因为iPhone操作系统负责处理视图的分层。只需向缓冲区写入一次,其余的由操作系统处理。这与其他编程环境不同,在其他编程环境中,每当有东西经过您的视图时,您需要不断地重新绘制。

在调用
drawRect:
时,始终准备好绘制视图的适当区域


虽然系统可能会缓冲您的视图,但这只能避免调用
drawRect:
。如果出于某种原因,系统必须使缓冲区无效,则可以再次调用
drawRect:
方法。另外,
drawRect:
将为视图的不同区域调用,因为滚动和其他影响视图区域可见性的操作会使视图的不同区域可见。

各种Cocoa引用之间的一些混淆源于Leopard中引入的层背视图。在iPhone上,所有UIView都是层备份的,在Leopard视图中,需要手动启用层备份

对于层备份视图,使用
drawRect()
中提供的内容绘制一次内容,然后缓冲到层中。该层的行为类似于矩形纹理,因此,当您移动层背景视图或覆盖它时,不需要重新绘制,纹理只需通过GPU移动到该位置。除非将图层的
needsdisplaynboundschange属性设置为
YES
,否则更改图层(或其包含视图)的大小只会缩放内容。这可能会导致视图或图层中的图形模糊,因此在这种情况下,您可能需要强制重新绘制
setNeedsDisplay
将触发手动重画视图或图层的内容,并随后在图层中重新绘制该内容

为了获得最佳性能,建议您避免频繁调用
drawRect
,因为层中的石英绘制和重铸是昂贵的操作。最好尝试使用可以移动或缩放的单独层制作动画

您所看到的与桌面相关的基于Cocoa的引用可能采用非层备份的视图,这会调用drawRect:任何时候需要更新视图,无论是移动、缩放还是部分视图被遮挡。正如我所说,所有UIView都是分层的,所以iPhone上的情况并非如此

也就是说,对于绘图应用程序,一种方法是维护绘制对象的数组并调用drawRect:每次用户添加新的内容时,按顺序迭代先前绘制的每个对象。我可能会建议另一种方法,即为每个图形操作创建新的UIView或CALayer。该绘图操作的内容(直线、圆弧、X等)将由单个视图或图层绘制。这样,您就不必在新的触摸屏上重新绘制所有内容,并且可以通过独立地移动每个绘制的元素来进行一些整洁的矢量样式编辑。对于复杂的绘图,这可能会有一点内存折衷,但我敢打赌它会有更好的绘图性能(最小的CPU使用和闪烁)

drawRect()只是一个执行绘图代码的钩子吗

这意味着使用当前图形上下文堆栈重新绘制传递给您的区域(rect)。没有了

或者这种方法也应该重新绘制“损坏”的区域,并且需要重新绘制

否。如果脏区域不重叠,您可能会收到多个调用
drawRect:
,并将不同的rect传递给您。使用
setNeedsDisplayInRect:
使矩形无效。如果只需重新绘制视图曲面的一部分,则将要求您在绘制时绘制该部分

我可以只画一次我的东西,然后它“粘住”吗?或者我必须随时通过drawRect()重新绘制整个场景吗

它不会“粘住”。在应用程序执行期间,矩形将失效,当视图系统需要更新屏幕时,您需要重新绘制这些矩形。仅重新绘制请求的rect

在某些情况下,一个简单的