Challenge: Dynamic Layer Content


#1

I was able to draw Hypno.png with varying opacity, but I did this without giving boxLayer a delegate.

Why do we need to give boxLayer a delegate?

In HypnosisView.m:

#import "HypnosisView.h"

@implementation HypnosisView
@synthesize xshift, yshift;
@synthesize stripeColor;

- (void)touchesBegan:(NSSet *)touches 
           withEvent:(UIEvent *)event
{
    UITouch *t = [touches anyObject];
    CGPoint p = [t locationInView:self];
    [boxLayer setPosition:p];
    
    float positionOpacity = (400 - [boxLayer position].y) / 400.0;
    UIColor *reddish = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:positionOpacity];
    CGColorRef cgReddish = [reddish CGColor];
    [boxLayer setBackgroundColor:cgReddish];
}

- (void)touchesMoved:(NSSet *)touches 
           withEvent:(UIEvent *)event
{
    UITouch *t = [touches anyObject];
    CGPoint p = [t locationInView:self];
    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    [boxLayer setPosition:p];
    [CATransaction commit];
    
    float positionOpacity = (400 - [boxLayer position].y) / 400.0;
    UIColor *reddish = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:positionOpacity];
    CGColorRef cgReddish = [reddish CGColor];
    [boxLayer setBackgroundColor:cgReddish];
}

Is there some sort of advantage to assigning a delegate and making it do this work?


#2

Ok, I understand my silly mistake. I was just changing the opacity of the background.

To change the opacity of the image itself I would need the delegate to perform Core Graphics calls on a context containing the image.

Here’s my solution:
First declare the ivar in HypnosisViewController.h as opposed to HypnosisView.h:

@interface HypnosisViewController : UIViewController <UIAccelerometerDelegate> 
{
    CALayer *boxLayer;
}


@end

Then, in HypnosisViewController.m:

- (void)loadView
{
    HypnosisView *hv = [[HypnosisView alloc] initWithFrame:CGRectZero];
    [hv setBackgroundColor:[UIColor clearColor]];
    
    boxLayer = [[CALayer alloc] init];
    [boxLayer setDelegate:self];
    [boxLayer setBounds:CGRectMake(0.0, 0.0, 85.0, 85.0)];
    [boxLayer setPosition:CGPointMake(160.0, 100.0)];
    
    UIColor *reddish = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.5];
    CGColorRef cgReddish = [reddish CGColor];
    [boxLayer setBackgroundColor:cgReddish];
    
    [[hv layer] addSublayer];
    
    [boxLayer setNeedsDisplay];
    
    [self setView:hv];
    [boxLayer release];
    [hv release];
    
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
    if (layer == boxLayer)
    {
        CGContextSetAlpha(ctx, (400.0 - [boxLayer position].y) / 400.0);
        UIImage *layerImage = [UIImage imageNamed:@"Hypno.png"];
        CGRect boundingBox = CGContextGetClipBoundingBox(ctx);
        
        CGContextTranslateCTM(ctx, 0, boundingBox.size.height);
        CGContextScaleCTM(ctx, 1.0, -1.0);
        
        CGContextDrawImage(ctx, boundingBox, [layerImage CGImage]);
        
    }
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *t = [touches anyObject];
    CGPoint p = [t locationInView:[self view]];
    [boxLayer setPosition:p];
    
    [boxLayer setNeedsDisplay];
    
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *t = [touches anyObject];
    CGPoint p = [t locationInView:[self view]];
    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    [boxLayer setPosition:p];
    [CATransaction commit];
    
    [boxLayer setNeedsDisplay];
}

You’ll notice in the drawLayer:inContext: method these two lines:

CGContextTranslateCTM(ctx, 0, boundingBox.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);

This is because for some reason, the image gets flipped upside down.
I stole these lines of code from posts in the adjoining thread.
It seemed to fix the problem.


#3

For this exercise there doesn’t seem to be a difference in the CGRects that are returned between these two code:

and

My question is are there situations when one is chosen over the other?

Thanx in advance!