CGContextSaveGState疑惑

要想了解CGContextSaveGState,首先得了解 Core Graphics

使用 Core Graphics ,我们几乎可以做任何我们想要的绘制任务,包括一些图片不好解决的自定义视图。
使用贝塞尔曲线+Core Graphics,我们自定义一些图形视图。因为有UIKitCore Graphics两套接口,所以塞尔曲线+Core Graphics的组合可以很灵活的组合。这个就要靠我们自己的大量练习来熟悉了。

绘制图形方法简介

所有的绘制必须在一个画布上操作,而我们能接触到的绘制相关的内容就只有** 图形上下文(CGContextRef) **了,我们所有的绘制都是在当前画布关联的 context上下文中进行,包括定制颜色、边框、外形等属性,然后执行fillstroke进行绘制任务。

图形上下文 CGContextRef

绘制这个操作,必须在 当前 上下文中执行才有效。
获取或者创建 当前 上下文的方法有二:

  1. 在UIView的子类的 drawRect: 方法中直接获取:
    UIGraphicsGetCurrentContext();
  2. 直接创建(好处是可以在任意地方自定义,但是画布的图形只能通过生成image传递出去):
    UIGraphicsBeginImageContextWithOption(size, opaque, scale); // 创建一个图片图形上下文;
    size:要绘制的矩形尺寸;
    opaque:YES:不透明,NO:透明;如果传递了NO,则出来的图片是黑色背景;
    scale:一般设置0,跟设备屏幕的scale一致;
    UIGraphicsGetCurrentContext(); // 获取创建的图形上下文;

设置属性

  1. 颜色
    UIKit方法:
    UIColor* color;
    [color setFill]; // 填充颜色
    [color setStroke]; // 线条颜色
    Core Graphics方法:
    CGContextSetFillColorWithColor(context, color.CGColor);
    CGContextSetStrokeColorWithColor(context, color.CGColor);

  2. 形状
    UIBezierPath画图形:
    UIBezierPath* path = [UIBezierPath bezierPathWithOvalInRect:rect]; // 创建UIKit版的path
    [path fill]; // 在path上绘制(填充)
    [path stroke]; // 在path上绘制(描边)
    Core Graphics方法:
    CGContextAddOvalInRect(context, rect); // a.创建一个椭圆形状
    CGContextFillOvalInRect(context, rect); // b.创建并绘制一个椭圆形状

执行绘制

UIKit绘制方法:

    [path fill]; // 在path上绘制(填充)
    [path stroke]; // 在path上绘制(描边)

Core Graphics绘制方法:

    CGContextFillPath(context); // (填充)单独的绘制,创建形状是在上面的 设置属性/2.形状下面的Core Graphics方法
    CGContextFillOvalInRect(context, rect); // (填充)创建形状,并绘制,同时进行的
    CGContextStrokePath(context); //  (描边)绘制
    CGContextStrokeOvalInRect(context, rect); // (描边)绘制

CGContextSaveGState

图形的绘制我们知道了,就是创建一个图形上下文(或者直接获取),然后在上下文中,设置属性,然后绘制。
但是,如果我们要在不同的线程或方法中,通过传递context来绘制图片或text时,就要考虑到,我即将要修改的属性,不应该影响当前context中的属性的值。
比如,如果我开始对context的一个属性设置了值,我传递context到另一个地方去执行其他的绘制,我肯定希望回来后,这个属性还是原来的值,而不是被修改了的新的值。
这个时候,CGContextSaveGState就派上用场了:
CGContextSaveGState必须要跟CGContextRestoreGState配套使用:

    CGContextSaveGState(context); 
    // 设置属性...
    // 执行绘制...
    CGContextRestoreGState(context);
  • CGContextSaveGState 作用:
    将当前图形上下文,push到CGContextRefs栈顶,相当于是拷贝了一份context到临时栈区,然后修改属性,并绘制。
    但是绘制的动作还是会在当前画布生效,只不过我在栈区修改的属性,不会影响到当前的context;
    当Restore后,属性还是会恢复到原来的值。
  • ** CGContextRestoreGState 作用:**
    将save到栈顶的context出栈,恢复到save前的图形上下文状态。
    如果在出栈前,还未绘制,则在save的context中修改的属性都会无效了。

总结:

如果context是要传递到不同的地方去绘制,那么一定要用 CGContextSaveGState 将context保存到栈顶,然后绘制。当前,前提是这个context是currentContext。否则,就要用CGContextPushContext了。
因为,我无法保证在其他地方修改属性,不会改掉我初始的属性状态。

你可能感兴趣的:(CGContextSaveGState疑惑)