我正在使用Core Graphic的一些内容,我正在寻找一些关于几个主题的补充说明。
的drawRect: 我对此有所了解,并且知道它是UIView的所有绘图方面的所在,但我不清楚场景背后发生了什么。当我创建UIView并填写drawRect然后将另一个对象的UIView设置为自定义视图时会发生什么?什么时候调用drawRect?
CGGraphicsContext: 我知道这是什么目的并理解这个概念,但我无法确切地知道它是如何工作的。 例如:
CGContextSaveGState(context);
CGContextAddRect(context, rect);
CGContextClip(context);
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
CGContextRestoreGState(context);
上面的代码在我的应用中并正常工作。困扰我的是它是如何工作的。保存/恢复上下文的想法是有道理的,但看起来我实际上是在保存上下文,使用完全相同的上下文进行更改,然后再次恢复相同的上下文。它似乎就像我正在保存一个上下文然后在该上下文之上编写,只是为了恢复它。它如何被保存到一个点,当你恢复它时,它是一个不同于用于进行更改的上下文的实例?在每种情况下都使用相同的变量上下文引用。
最后,我将非常感谢有关使用Core Graphics的练习项目或示例的任何资源。我希望提高我在这方面的技能,因为我显然目前没有多少。
答案 0 :(得分:3)
当我创建UIView并填写drawRect然后将另一个对象的UIView设置为自定义视图时会发生什么?什么时候调用drawRect?
将视图添加到“实时”视图图表会将视图的帧标记为需要显示。然后,主运行循环创建并合并无效的rects,并很快返回以调用绘图。失效时不会立即绘制。这是一件好事,因为调整大小会导致严重的透支 - 多余的工作会导致许多应用程序的绘图性能下降。绘图时,会创建一个上下文来渲染 - 最终输出到目的地。
图形上下文是可以自由地为其目的地工作的抽象 - 目的地可以是设备/屏幕,位图,PDF等。但是,上下文句柄(CGContextRef
)本身指的是destination并保存一组有关其状态的参数(these parameters are all documented here)。这些参数集的操作类似于堆栈:Push = CGContextSaveGState
,Pop = CGContextRestoreGState
。虽然上下文指针没有改变,但参数集的堆栈正在改变。
就资源而言,请参阅Programming with Quartz。它现在已经8年了,最初是为OS X编写的 - 但最终并不重要,因为绘图系统和API的基本原理从那时起就没有显着发展 - 这就是你想要的专注在。 API已经扩展,因此最好回顾一下自10.4以来引入的API,看看它们解决了哪些问题,但这对你来说是一件好事,因为它有助于保持对绘图系统基本操作的关注。请注意,某些功能被排除在iOS之外(例如,通常由于浮点性能和内存限制,我认为),因此每个示例可能无法在iOS上使用,但我知道没有更好的指南。 / p>
提示:如果使用Quartz而不是AppKit / UIKit,您的绘图代码可以在OS X和iOS上轻松重用。此外,Quartz API的更新频率较低(即API往往使用寿命更长)。
答案 1 :(得分:2)
-drawRect:在您(例如您的视图控制器)调用视图的方法-setNeedsDisplay或-setNeedsDisplayInRect后,在某个时刻被调用:。
保存图形状态会将当前图形状态推送到堆栈上。图形状态包含填充和描边设置,当前转换矩阵等。有关详细信息,请参阅Apple's documentation。
Quartz 2D Programming Guide不包含很多例子,但在其他方面非常彻底。
答案 2 :(得分:0)
对于石英/核心图形,上下文实际上是一组当前参数,用于在上一个图形之上绘制下一个绘图命令。
保存状态让我们保存所有这些参数,以便以后的绘图命令重用它们。
然后,您可以为某些绘图命令设置不同的参数集。
恢复状态会让你回到原来的位置。
我推荐这本书 用Quartz编程 Mac OS X中的2D和PDF图形
虽然在某些方面有点过时,但它会真正教你石英/核心图形如何真正流动。
答案 3 :(得分:0)
好的,这是一个非常深入的话题。我会向我的理解和解释一些事情。尽量保持简单。如果我弄错了,我希望有人可以纠正我。
首先是屏幕绘图和屏幕外绘图的概念。在屏幕上绘制是在GPU中进行的,其中在CPU中进行屏幕外绘制以绘制事物,然后将其给予GPU以在屏幕上显示。那是drawRect()进入的地方(drawrect只是一种做btw外屏图纸的方法)。这就是为什么在drawRect模板方法中(你会看到当你创建UIView的子类时)Apple会发表评论
“仅覆盖drawRect:如果执行自定义绘图。空实现会对动画期间的性能产生负面影响”
原因是只要有drawRect方法,iOS就必须要求CPU关注drawRect中的绘图并将其交给GPU。 (不要认为这是一件坏事:))。这就是drawRect在抽象级别中发生的情况。
现在讨论为什么要保存&反复恢复相同的上下文。您是否尝试在apple doc中阅读有关保存/恢复上下文的方法说明?如果有,你会发现它显示了受此影响的所有图形状态。好的,这有什么帮助?
考虑这样的事情。假设您正在绘制一个矩形,您必须在其右半部分限制绘图的下一部分并使用阴影和抗锯齿等。您可以在绘制右侧之前保存上下文并设置您想要的任何属性一旦完成,您就可以简单地恢复上下文,并且可以继续使用之前的所有设置,而无需再次明确设置它们。当你做复杂的绘图时,这也是一个很好的做法,否则会产生你可能没想到的奇怪结果。类似这样的事情
- drawRect()
{
CGContextSaveGState(context);
drawLeftPart(); // - 1
drawRightPart(); // - 2
someOtherDrawing(); // - 3
CGContextRestoreGState(context);
}
- drawLeftPart()
{
CGContextSaveGState(context);
// do your drawing
CGContextRestoreGState(context);
}
- drawRightPart()
{
CGContextSaveGState(context);
// do your drawing
CGContextRestoreGState(context);
}
- someOtherDrawing()
{
CGContextSaveGState(context);
// do your drawing
CGContextRestoreGState(context);
}
现在你在第1部分中设置的属性不会影响第2部分和第2部分的绘制。等等。
希望这有帮助,