Jacksonkr Jacksonkr - 6 months ago 19
Objective-C Question

iOS - Quartz drawing issue with parent/child views

Scenario

I have two views. One is the "parent" view which contains a "child" view that does the drawing. I refer to the child as QuartzView in the code to follow. QuartzView knows how to draw a square to it's own context.

Issue

When I tell the QuartzView on it's

self
to draw a square it does so as expected. When I use the parent view to tell QuartsView to draw a square on it's
self
it draws the square in the lower left corner of the screen at about 1/5 the expected size.

Question

I assume there's some parent/child or context issues here but I'm not sure what they are. How can I get both squares to draw in the exact same place at the exact same size?

Parent
ViewController



- (void)drawASquare {

// this code draws the "goofy" square that is smaller and off in the bottom left corner
x = qv.frame.size.width / 2;
y = qv.frame.size.height / 2;
CGPoint center = CGPointMake(x, y);
[qv drawRectWithCenter:center andWidth:50 andHeight:50 andFillColor:[UIColor blueColor]];

}


Child
QuartzView



- (void)drawRect:(CGRect)rect
{
self.context = UIGraphicsGetCurrentContext();
UIColor *color = [UIColor colorWithRed:0 green:1 blue:0 alpha:0.5];

// this code draws a square as expected
float w = self.frame.size.width / 2;
float h = self.frame.size.height / 2;
color = [UIColor blueColor];
CGPoint center = CGPointMake(w, h);
[self drawRectWithCenter:center andWidth:20 andHeight:20 andFillColor:color];
}

- (void)drawRectWithCenter:(CGPoint)center andWidth:(float)w andHeight:(float)h andFillColor:(UIColor *)color
{
CGContextSetFillColorWithColor(self.context, color.CGColor);
CGContextSetRGBStrokeColor(self.context, 0.0, 1.0, 0.0, 1);

CGRect rectangle = CGRectMake(center.x - w / 2, center.x - w / 2, w, h);

CGContextFillRect(self.context, rectangle);
CGContextStrokeRect(self.context, rectangle);
}


Note


  • The opacities are the same for both squares

  • I turned off "Autoresize subviews" with no noticeable difference

  • view.contentScaleFactor = [[UIScreen mainScreen] scale];
    has not helped



Edit



I'm noticing that the x/y values of the square when drawn the parent starting from the bottom left as 0,0 whereas normally 0,0 would be the top left.

Answer

The return value from UIGraphicsGetCurrentContext() is only valid inside the drawRect method. You can not and must not use that context in any other method. So the self.context property should just be a local variable.

In the drawRectWithCenter method, you should store all of the parameters in properties, and then request a view update with [self setNeedsDisplay]. That way, the framework will call drawRect with the new information. The drawRectWithCenter method should look something like this

- (void)drawRectWithCenter:(CGPoint)center andWidth:(float)w andHeight:(float)h andFillColor:(UIColor *)color
{
    self.showCenter = center;
    self.showWidth = w;
    self.showHeight = h;
    self.showFillColor = color;
    [self setNeedsDisplay];
}

And of course, the drawRect function needs to take that information, and do the appropriate drawing.

Comments