Handling touches with CALayer


#1

I’m trying to adapt what I’ve learned in Ch. 18 for a simple app, but I’m not totally getting the relationship between CALayer and UIView. I want the user to be able to drag and drop ObjectA onto ObjectB, and then have ObjectB change its appearance. CALayer seems to be the way to do this.

I created a new project named “Touch” with the “View-Based Application” template in Xcode. I added an instance variable CALayer *boxLayer to TouchViewController, and implemented viewDidLoad this way:

- (void)viewDidLoad { [super viewDidLoad]; boxLayer = [[CALayer alloc] init]; boxLayer.bounds = CGRectMake(0, 0, 85.0, 85.0); boxLayer.position = CGPointMake(160.0, 100.0); boxLayer.backgroundColor = [UIColor greenColor].CGColor; boxLayer.shadowOffset = CGSizeMake(1, 3); boxLayer.shadowRadius = 5.0; boxLayer.shadowColor = [UIColor blackColor].CGColor; boxLayer.shadowOpacity = 0.8; boxLayer.cornerRadius = 10.0; boxLayer.borderColor = [UIColor blackColor].CGColor; boxLayer.borderWidth = 2.0; [self.view.layer addSublayer]; [boxLayer release]; }
Also in TouchViewController, I implemented these methods.

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

  • (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint p = [touch locationInView:self.view];
    [CATransaction begin];
    [CATransaction setValue:[NSNumber numberWithBool:YES]
    forKey:kCATransactionDisableActions];
    [boxLayer setPosition:p];
    [CATransaction commit];
    }[/code]
    This works exactly as expected. When I tap somewhere on the screen, the boxLayer object animates to that position. I can also touch the boxLayer and drag it around the screen.

As I mentioned above, I now want to put two different objects on the screen and drag ObjectA onto ObjectB. I think this means I need to implement the touchesBegan and touchesMoved methods in a UIView subclass for ObjectA. This way it will only respond when touched directly.

As a UIView subclass, ObjectA should have its own layer. Can I implement code in ObjectA to set up its layer as I previously did in TouchViewController? Can I also implement methods to have it respond to touches? I tried adapting the code from viewDidLoad above and adding it to drawRect for ObjectA, but this just gave me a black square. Is this the right approach to my problem, or should I be doing things differently?

Thanks,
Jack


#2

I wonder if the ‘squash the bug’ section of this (great) tutorial would give you a hint as to how to solve your problem: raywenderlich.com/2454/how-t … n-tutorial specifically the section around: CGPoint touchLocation = [touch locationInView:self.view];