Setting Line Parameters
Each context stores line width as part of its graphics state. You can adjust that line width by calling CGContextSetLineWidth() and passing the point size as its parameter. Subsequent drawing operations inherit the change in that state. That width does not, however, apply to UIBezierPath instances, the primary drawing tool for UIKit. Every UIKit path permits you to adjust its stroke width by setting its lineWidth parameter. Whatever value this is set to wins out over any context settings.
Take a look at Listing 1-14. It creates a path and sets its line width to 4. Then it instructs the context to use a 20-point-wide line. Figure 1-16 shows the result of these drawing requests. As the image demonstrates, drawing the path through Quartz honors that 20-point width. Drawing through UIKit overrides the context state with the path parameter.
Listing 1-14 Conflicting Line Widths
UIGraphicsBeginImageContext(bounds.size); CGContextRef context = UIGraphicsGetCurrentContext(); // Build a Bezier path and set its width UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:32]; path.lineWidth = 4; // Update the context state to use 20-point wide lines CGContextSetLineWidth(context, 20); // Draw this path using the context state [purpleColor set]; CGContextAddPath(context, path.CGPath); CGContextStrokePath(context); // Draw the path directly through UIKit [greenColor set]; [path stroke];
Figure 1-16 Some Quartz context semantics are implemented orthogonally to UIKit. The smaller interior stroke does not inherit the context’s default line width.
UIKit’s approach binds line width semantics to the UIBezierPath object and not to the context as a whole. That’s not a bad thing. Pushing a line width state in order to draw a shape makes less sense than associating that width with a particular object. It is not, however, a consistent thing. This approach is not universal—at least not yet. You can see this by trying out dashes.
Dashes
Dash patterns do not demonstrate the UIKit/Quartz dichotomy seen with line width. Changes made to the context state will affect UIKit paths, whether you use the UIKit or Quartz entry points. To set a path’s dash pattern in UIKit, use the setLineDash:count:phase: method.
This code snippet creates the output shown in Figure 1-17:
[greenColor set]; CGFloat dashes[] = {6, 2}; [path setLineDash:dashes count:2 phase:0]; [path stroke];
Figure 1-17 Dashes can be set in the context state or applied to a path instance.
This snippet uses three arguments. The first sets the dash pattern (6 points on, 2 points off), the second counts the first argument (2 items), and the third specifies a phase offset—that is, how far into the pattern to start. 0 means default to the normal layout pattern. You’ll read more about dashes in Chapter 4.
The same effect can be applied to the context as a whole by calling the equivalent Quartz function, CGContextSetLineDash(). This next code snippet also produces the output shown in Figure 1-17. It just gets there in a different way:
[greenColor set]; CGFloat dashes[] = {6, 2}; CGContextSetLineDash(context, 0, dashes, 2); [path stroke];