CGContext vs CALayer

2019-02-05 08:21发布

问题:

I'm trying to get a handle on Quartz 2D and looking at the online book Quartz 2D Graphics for Mac OS X Developers.

One very basic thing that is confusing me is the CGContext. For example, I can draw a simple "U" shape with the code below and use it in a CAShapeLayer without referencing a CGContext. Is the context implied/provided by default by the CAShapeLayer?

I'm probably mixing up several iOS/OSX graphics APIs here so maybe someone can clarify where I am going wrong.

CGPoint pt1 =  CGPointMake(100, 100);
CGPoint pt2 =  CGPointMake(150, 100);
CGPoint pt3 =  CGPointMake(150, 200);
CGPoint pt4 =  CGPointMake(190, 200);
CGPoint pt5 =  CGPointMake(190, 100);
CGPoint pt6 =  CGPointMake(210, 100);
CGPoint pt7 =  CGPointMake(210, 250);
CGPoint pt8 =  CGPointMake(100, 250);
CGPoint pt9 =  CGPointMake(100, 100);

CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, nil, pt1.x,pt1.y);
CGPathAddLineToPoint(path, nil, pt2.x, pt2.y);
CGPathAddLineToPoint(path, nil, pt3.x, pt3.y);
CGPathAddLineToPoint(path, nil, pt4.x, pt4.y);
CGPathAddLineToPoint(path, nil, pt5.x, pt5.y);
CGPathAddLineToPoint(path, nil, pt6.x, pt6.y);
CGPathAddLineToPoint(path, nil, pt7.x, pt7.y);
CGPathAddLineToPoint(path, nil, pt8.x, pt8.y);
CGPathAddLineToPoint(path, nil, pt9.x, pt9.y);

CAShapeLayer *shapeLayer = [CAShapeLayer layer];
[self.view.layer addSublayer:shapeLayer];

回答1:

Yes, the CAShapeLayer will draw the path into a context for you.

Note that with CAShapeLayer, you use CGPath, whereas if you're drawing into a context yourself, you may want to use CGContext's own path-drawing functions instead.

The biggest difference is that the CGContext path functions add commands directly into the context's current path, to be thrown away when you tell the context to fill or stroke (or explicitly abandon) the path, whereas a CGPath object keeps them around to be reused again and again—e.g., if you change the CAShapeLayer's drawing properties.

Of course, there are cases for using CGPath even when you're going to draw it into a context. If the set of commands never changes, then it's a potential optimization; it makes transforming the path easy; you can iterate on its commands (e.g., to export them to a file) afterward. You can also write the plotting code with UIBezierPath (i.e., with Objective-C messages) and then ask it for a CGPath.

Using CGContext in either way isn't wrong, and there probably are cases in which it's best, but CAShapeLayer is the easiest way for most purposes, particularly in Cocoa Touch, where every UIView is backed by a CALayer that you could put the CAShapeLayer into.