My gold challenge solution


#1

One question:
In the book, there’s the following code:

// Figure out the center of the bounds rectangle CGPoint center; center.x = bounds.origin.x + bounds.size.width / 2.0; center.y = bounds.origin.y + bounds.size.height / 2.0;

Why use bounds.origin at all if they’re always gonna be 0,0? Isn’t it more logical to have only this?

// Figure out the center of the bounds rectangle CGPoint center; center.x = bounds.size.width / 2.0; center.y = bounds.size.height / 2.0;

anyway, here’s my BNRHypnosisView.m. Comments are always welcome.

[code]#import “BNRHypnosisView.h”

@implementation BNRHypnosisView

  • (id)initWithFrame:(CGRect)frame
    {
    self = [super initWithFrame:frame];
    if (self) {
    // ALL BNRHypnosysViews start with a clear background color
    self.backgroundColor = [UIColor clearColor];
    }
    return self;
    }

// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.

  • (void)drawRect:(CGRect)rect
    {
    CGRect bounds = self.bounds;

    // Figure out the center of the bounds rectangle
    CGPoint center;
    center.x = bounds.origin.x + bounds.size.width / 2.0;
    center.y = bounds.origin.y + bounds.size.height / 2.0;

    // The largest circle will circumscribe the view
    float maxRadius = hypot(bounds.size.width, bounds.size.height) / 2.0;

    UIBezierPath *path = [[UIBezierPath alloc] init];

    for (float currentRadius = maxRadius; currentRadius >0; currentRadius -=20) {
    [path moveToPoint:CGPointMake(center.x + currentRadius, center.y)];

      [path addArcWithCenter:center
                      radius:currentRadius // Note this is currentRadius!
                  startAngle:0.0
                    endAngle:M_PI * 2.0
                   clockwise:YES];
    

    }

    // Configure the line width to 10 points
    path.lineWidth = 10;

    // Configure the drawing color to light gray
    [[UIColor lightGrayColor] setStroke];

    // Draw the line!
    [path stroke];

    // Get and store the current context
    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    CGContextSaveGState(currentContext);

    // Add a gradient triangle
    UIBezierPath *triangle = [[UIBezierPath alloc]init];

    CGFloat locations[2] = { 0.0, 1.0};
    CGFloat components[8] = {.0, 1.0, 0.0, 1.0, // Start color is green
    1.0, 1.0, 0.0, 1.0 }; // End color is yellow

    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
    CGGradientRef gradient = CGGradientCreateWithColorComponents(colorspace, components, locations, 2);

    // Set the top of the triangle, and use it as the start of the gradient
    CGPoint triangleTop;
    triangleTop.x = bounds.size.width / 2.0;
    triangleTop.y = bounds.size.height * 0.20;

    // Set the bottom (center) of the triangle, and use it and the end of the gradient
    CGPoint triangleBottom;
    triangleBottom.x = bounds.size.width / 2.0;
    triangleBottom.y = bounds.size.height * 0.80;

    // Set the bottom points of the triangle
    CGPoint triangleBottomLeft;
    CGPoint triangleBottomRight;
    triangleBottomLeft.x = bounds.size.width * 0.2;
    triangleBottomLeft.y = triangleBottom.y;
    triangleBottomRight.x = bounds.size.width * 0.8;
    triangleBottomRight.y = triangleBottom.y;

    // Make the clipping triangle
    [triangle moveToPoint:triangleBottomLeft];
    [triangle addLineToPoint:triangleBottomRight];
    [triangle addLineToPoint:triangleTop];
    [triangle closePath];
    [triangle addClip];

    CGPoint startPoint = triangleTop;
    CGPoint endPoint = triangleBottom;
    CGContextDrawLinearGradient(currentContext, gradient, startPoint, endPoint, 0);

    // Clean up
    CGGradientRelease(gradient);
    CGColorSpaceRelease(colorspace);
    CGContextRestoreGState(currentContext);

    // Make shadows
    CGContextSaveGState(currentContext);
    CGContextSetShadow(currentContext, CGSizeMake(4, 7), 3);

    // Insert image
    UIImage *logo = [UIImage imageNamed:@“logo.png”];
    [logo drawInRect:bounds];

    CGContextRestoreGState(currentContext);

}

@end
[/code]


#2

Although it usually is (0, 0), the bounds of a UIView instance can be something else. When you get into more advanced view transformations, you are likely to see this.
UIScrollView (which comes up later in the book) has a different origin depending upon which part of its child view you are looking at. Try it for yourself once you’ve completed the next chapter that introduces UIScrollView.


#3

thanks!


#4

HI
I was somewhat stuck in this and your code helped me a lot. Looks like it is working great. :smiley:


#5

[quote=“larsoleruben”]HI
I was somewhat stuck in this and your code helped me a lot. Looks like it is working great. :smiley:[/quote]

Glad to hear!!