在 iPhone 上使用 Quartz 时如何保留之前的绘图?

Posted

技术标签:

【中文标题】在 iPhone 上使用 Quartz 时如何保留之前的绘图?【英文标题】:How to keep the previous drawing when using Quartz on the iPhone? 【发布时间】:2010-09-28 19:41:54 【问题描述】:

我想在 iPhone 上通过触摸并在屏幕上拖动来画一条简单的线。我设法通过继承 UIView 并更改默认的 drawRect: 方法来做到这一点。同时在我的视图控制器中,我检测到触摸事件并在必要时调用 [myView setNeedsDisplay]。问题是当我尝试绘制第二条线时,前一条线消失了。有没有办法在屏幕上保留上一行?

我们将不胜感激任何输入。

【问题讨论】:

【参考方案1】:

通常的方法是使用CGBitmapContextCreate()。在 -init/-init-WithFrame:/etc 中创建它并在 -dealloc 中调用 CGContextRelease()。我不确定您如何使用 CGBitmapContextCreate() 处理“视网膜显示”的 2 倍比例。

(UIGraphicsBeginImageContext() 更简单,但做UIGraphicsBeginImageContext(); myContext = CFRetain(UIGraphicsGetCurrentContext()); UIGraphicsEndImageContext(); 可能不安全。)

然后做类似的事情

#import <QuartzCore/CALayer.h>

-(void)displayLayer:(CALayer*)layer

  UIGraphicsPushContext(mycontext);
  ... Update the bitmap context by drawing a line...
  UIGraphicsPopContext();
  CGImageRef cgImage = CGBitmapContextCreateImage(mycontext);
  layer.contents = (id)cgImage;
  CFRelease(cgImage);

为了提高效率,我使用了-displayLayer:(一个 CALayer 委托函数;一个 UIView 是它的层的委托)而不是 -drawRect::如果你使用 -drawRect:,CALayer 会创建一个 second 上下文(因此是位图的第二个副本)。


或者,您可能对 CGLayer 有好运。我从未见过使用它来代替位图上下文的理由;它可能在某些情况下更有效。


或者,您可能可以摆脱设置self.clearsContextBeforeDrawing = NO但这很可能会中断。 UIKit(或更准确地说,CoreAnimation)希望您绘制包含在剪辑 rect 中的整个视图(这是-drawRect: 的“rect”参数;不保证是边界)。如果您的视图离开屏幕,CoreAnimation 可能会决定它想要返回内存。或者 CoreAnimation 可能只绘制屏幕上的视图部分。或者 CoreAnimation 可能会进行双缓冲绘图,导致您的视图看起来在两种状态之间翻转。

【讨论】:

【参考方案2】:

如果你使用drawRect:来绘制,那么你需要绘制整个区域。因此,您不仅需要存储最新部分的数据,还需要存储所有内容。

作为替代方案,您可以直接在位图中绘制,或为线条动态生成子视图(仅对非常有限的绘图有意义(即一些基于矢量的东西)。

【讨论】:

以上是关于在 iPhone 上使用 Quartz 时如何保留之前的绘图?的主要内容,如果未能解决你的问题,请参考以下文章

我在 iPHone 上的 Quartz 绘图在旋转后被剪掉了!

在 iPhone 上使用自动释放时如何解决问题?

iPhone:Quartz2d 与 OpenGL ES

iPhone开发中如何制作这种动画效果? Quartz 2d,Vore 动画?

如何在 iPhone / iPad 的应用程序中正确使用保留和释放

如何使用 Quartz 在 UIView 上绘制子视图