CGContextSaveGState与UIGraphicsPushContext的区别

原文地址点击打开链接

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    // do drawing here
    CGContextRestoreGState(context);

}



- (void)drawRect:(CGRect)rect 
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    UIGraphicsPushContext(context);
    // do drawing here
    UIGraphicsPopContext(); 
}


Questions: What is the difference between those methods? Which one is better to use? Are there some examples of proving one method better than other and vise versa?


Answer:UIGraphicsPushContext(context) pushes context onto a stack of CGContextRefs (making context the current drawing context), whereas CGContextSaveGState(context) pushes the current graphics state onto the stack of graphics states maintained by context. You should use UIGraphicsPushContext if you need to make a new CGContextRef the current drawing context, and you should use CGContextSaveGState when you're working with one graphics context and just want to save, for example: the current transform state, fill or stroke colors, etc.



在调用drawRect:方法之前,绘图系统创建了一个图形上下文(CGContext)。上下文包括大量信息,比如画笔颜色、文本颜色、当前字体、变形等。有时你可能想要修改上下文并使其恢复原样。举个例子,你现在有一个使用特定颜色绘制特定形状的函数。由于只能有一只画笔,因此在更改颜色后,就会影响调用函数的结果。为了避免这个副作用,你可以使用CGContextSaveGStateCGContextRestoreGState将上下文入栈和出栈。
请不要与看起来相似的UIGraphicsPushContextUIGraphicsPopContext混淆。它们做的并不是同一件事。CGContextSaveGState记录上下文的当前状态。UIGraphicsPushContext更改当前上下文。以下是CGContextSaveGState的示例。
1
2
3
4
5
    [[UIColor redColor] setStroke];
    CGContextSaveGState(UIGraphicsGetCurrentContext());
    [[UIColor blackColor] setStroke];
    CGContextRestoreGState(UIGraphicsGetCurrentContext());
    UIRectFill(CGRectMake(10, 10, 100, 100)); // 红
这段代码设置了画笔的颜色为红色并保存了上下文。之后它将把画笔颜色改成黑色并恢复上下文。这样当你绘图的时候,画笔又会变成红色了。
以下代码展示了一个常见的错误。
1
2
3
4
5
6
    [[UIColor redColor] setStroke];
    //下一行不对
    UIGraphicsPushContext(UIGraphicsGetCurrentContext());
    [[UIColor blackColor] setStroke];
    UIGraphicsPopContext();
    UIRectFill(CGRectMake(10, 10, 100, 100)); //
在这个示例中,画笔颜色设置为了红色,并且上下文切换为当前毫无用处的上下文。然后更改画笔的颜色为黑色,接着通过出栈使上下文回到原始状态(实际上等于什么都没做)。现在将会画一个黑色的矩形,这绝对不是你想要的。
使用UIGraphicsPushContext并不能保存上下文的当前**状态**(画笔颜色、线条宽度等),而是完全切换上下文。假设你正在当前视图上下文中绘制什么东西,这时想要在位图上下文中绘制完全不同的东西。如果要使用UIKit来进行任意绘图,你会希望保存当前的UIKit上下文,包括所有已经绘制的内容,接着切换到一个全新的绘图上下文中。这就是UIGraphicsPushContext的功能。创建完位图后,再将你的旧上下文出栈。而这就是UIGraphicsPopContext的功能。这种情况只会在要使用UIKit在新的位图上下文中绘图时才会发生。只要你使用的是Core Graphics函数,就不需要去执行上下文入栈和出栈,因为Core Graphics函数将上下文视作参数。
这是极其有用的常见操作。因为其常用性,苹果公司为其创建了一个叫做UIGraphicsBeginImageContext的快捷方式。它负责将旧的上下文入栈、为新上下文分配内存、创建新的上下文、翻转坐标系统,并使其作为当前上下文使用。它替你完成了大部分的工作



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值