在iPhone上使用Quartz时如何保留之前的绘图?
我想通过触摸并在屏幕上拖动来在 iPhone 上画一条简单的线条。我设法通过子类化 UIView 并更改默认的 drawRect: 方法来做到这一点。同时,在我的视图控制器中,我检测触摸事件并在必要时调用 [myView setNeedsDisplay]。问题是,当我尝试绘制第二条线时,前一行消失了。有没有办法在屏幕上保留上一行?
任何意见将不胜感激。
I want to draw a simple line on the iPhone by touching and dragging across the screen. I managed to do that by subclassing UIView and change the default drawRect: method. At the same time in my viewcontroller I detect the touch event and call the [myView setNeedsDisplay] when necessary. The problem is that when I try to draw the second line the previous line disappears. Is there a way to keep the previous line on the screen?
Any input will be very much appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
通常的方法是使用CGBitmapContextCreate()。在-init/-init-WithFrame:/etc中创建它并在-dealloc中调用CGContextRelease()。我不确定你如何使用 CGBitmapContextCreate() 处理“视网膜显示”的 2 倍比例。
(UIGraphicsBeginImageContext() 更容易,但执行
UIGraphicsBeginImageContext(); myContext = CFRetain(UIGraphicsGetCurrentContext()); UIGraphicsEndImageContext();
可能不安全。)然后执行类似
我使用过的操作 < code>-displayLayer: (CALayer 委托函数;UIView 是其图层的委托)而不是
-drawRect:
以提高效率:如果您使用-drawRect:
,CALayer 创建第二 上下文(从而创建位图的第二个副本)。或者,您可能会幸运地使用 CGLayer。我从未见过使用它而不是位图上下文的理由;在某些情况下它可能更有效。
或者,您可能可以通过设置
self.clearsContextBeforeDrawing = NO
来逃脱,但这很可能会被破坏。 UIKit(或者更准确地说,CoreAnimation)希望您绘制剪辑矩形中包含的整个视图(这是-drawRect:
的“rect”参数;它不保证是边界)。如果您的视图离开屏幕,CoreAnimation 可能会决定需要恢复内存。或者 CoreAnimation 可能只绘制屏幕上视图的部分。或者 CoreAnimation 可能会执行双缓冲绘制,导致您的视图看起来在两种状态之间翻转。The usual method is to use CGBitmapContextCreate(). Create it in -init/-init-WithFrame:/etc and call CGContextRelease() in -dealloc. I'm not sure how you handle the 2x scale of the "retina display" with CGBitmapContextCreate().
(UIGraphicsBeginImageContext() is easier, but it might not be safe to do
UIGraphicsBeginImageContext(); myContext = CFRetain(UIGraphicsGetCurrentContext()); UIGraphicsEndImageContext();
.)Then do something like
I've used
-displayLayer:
(a CALayer delegate function; a UIView is its layer's delegate) instead of-drawRect:
for efficiency: if you use-drawRect:
, CALayer creates a second context (and thus a second copy of the bitmap).Alternatively, you might have luck with CGLayer. I've never seen a reason to use it instead of a bitmap context; it might be more efficient in some cases.
Alternatively, you might get away with setting
self.clearsContextBeforeDrawing = NO
, but this is very likely to break. UIKit (or, more accurately, CoreAnimation) expects you to draw the whole view contained in the clip rect (that's the "rect" argument of-drawRect:
; it's not guaranteed to be the bounds). If your view goes offscreen, CoreAnimation might decide that it wants the memory back. Or CoreAnimation might only draw the part of the view that's on-screen. Or CoreAnimation might do double-buffered drawing, causing your view to appear to flip between two states.如果你使用drawRect:来绘制,那么你需要绘制整个区域。因此,您不仅需要存储最新部分的数据,还需要存储所有内容。
作为替代方案,您可以直接绘制位图,或为您的线条动态生成子视图(仅对非常有限的绘制有意义(即一些基于矢量的东西)。
If you use drawRect: to draw, then you need to draw the whole area. So you need to store not only the data for the latest part but everything.
As an alternative, you might draw directly into a bitmap, or generate dynamically subviews for your lines (makes only sense for very limited drawing (i.e. some few vector-based stuff).