iPhone - 试图弄清楚drawRect:

时间:2010-12-03 23:05:36

标签: iphone

我有我的这个应用程序,其中包含一个允许用户在屏幕上进行简单绘画的部分。我的想法是提供两种绘画:粗糙和平滑(bezier)线条。

如何构建:我有一个带有自定义drawRect方法的透明UIView。我不确定我是否完全了解drawRect,但代码部分正常工作。

工作原理:用户在屏幕上移动手指。当他第一次触摸屏幕时,TouchesBegan创建一个名为myPoints的mutablearray并存储第一个点的坐标并按原样存储画布(允许撤消)。

之后,TouchesMoved例程抓取所有点并将它们添加到myPoints。在用户选择绘制贝塞尔线的情况下需要该数组。

当检测到touchesEnded时,应用程序必须查看用户是否正在绘制常规线(粗略)或贝塞尔曲线。如果它不是bezier,则已绘制线条。如果需要贝塞尔曲线,我需要擦除画布,恢复画布,就像TouchesBegan存储它时一样,计算新的贝塞尔曲线近似值(反向设计为最佳贝塞尔曲线以适合绘制点)并绘制新曲线,取代粗糙的。

这些是我的问题:

1)如何存储撤消?我首先考虑创建一个新层来存储撤消,但这样做会将应用程序内存使用量从8增加到13 Mb ...我不确定这是否是一个安全级别(该应用程序与3GS,iPod兼容)触摸2nd G,向上,包括iPad)。然后,我决定触发一个队列操作来保存画布。这导致保存空白图像(我认为上下文的保存方法为零,因为它无法获取drawRect之外的上下文)。

2)第二个问题类似于第一个问题。此时我需要将画布恢复到保存时的状态,但由于恢复方法在drawRect之外,因此它也会对上下文无效。

TouchesBegan,TouchesMoved和TouchesEnded以及提到的所有方法都在drawRect所在的同一个类中,而不是在viewController中。

我的问题是:你们是怎么做到的?

我在商店看到了一个提供多级撤消的绘画应用程序。我无法想象他们是如何做到这一点的,因为在我的第一次尝试中,我创造了一层耗费5 Mb的内存,所以看起来不可能有这种类型的内存......

请帮助我......我很绝望!

谢谢

2 个答案:

答案 0 :(得分:1)

你为什么要存放“画布”? (我认为那是你正在画的图像吗?)

我认为您想要做的是将可绘制对象(粗线,贝塞尔等)存储在某个对象中,该对象具有“路径”中的所有点,然后您拥有一个集合(即一个nsmutablearray)你的可绘制对象....然后drawRect获取该集合并将其绘制到屏幕上。

可以实现撤消,因此当用户想要撤消时,从集合中删除最后一个可绘制对象或者添加到集合中的最后一个点并重绘...

您无法在drawRect之外获取绘图上下文,但您需要做的就是更新数据结构(点,可绘制对象等)并通过调用[self setNeedsDisplay]使控件“无效”,以便操作系统叫你是drawRect然后你可以把你的对象画到屏幕上。

编辑:

我创建了一个简单的概念证明应用程序(在c#winforms中......我现在无法访问我的mac,但很容易理解这个概念)。示例代码位于

https://github.com/jaimedp/DrawEraseUndo

请注意,如果你变得更复杂,这个概念会有一些限制,例如,如果你根据手指移动的速度看到线条的含义,重绘不会处理这个,虽然你可以添加更多可绘制对象的属性,以说明更多的幻想。

如果需要,我会将示例移植到iOS。

希望这会有所帮助..

答案 1 :(得分:1)

好的。保持...我想要得到你上面所说的......我最初认为我会好好回答......因为我之前做过类似的事情..但后来我读了你的整个问题并且由Jaime回答并且它让我很困惑..但是无论如何我都能解释...我可以给你一个答案

所以对于擦除的部分..我正在绘制你的点数组的帮助,你存储在触摸开始和移动...我想你只是画那样..所以擦除..我暂时清空我的点数组然后调用“setNeedsDisplay”..这将找不到数组中的点,因此将清除所有...

如果你在粗略绘图的情况下不使用数组绘图,那么我建议你这样做。

我还建议另外一件事......确定用户想要粗糙或平滑的曲线应该在开头而不是“touchesEnded”...然后用数组绘制......

我希望你知道如何画出粗糙的曲线和平滑曲线,我会给你一个链接到我的答案

CGContext Draw Line slowly responding to fast finger movement