views:

49

answers:

3

Hi, I've created a custom class AnimalView which is a subclass of UIView containing a UILabel and a UIImageView.

@interface AnimalView : UIView {
    UILabel *nameLabel;
    UIImageView *picture;
}

Then I added in several AnimalView onto the ViewController.view. In the touchesBegan:withEvent: method, I wanted to detect if the touched object is an AnimalView or not. Here is the code for the viewController:

@implementation AppViewController

- (void)viewDidLoad {
    UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:...
    [self.view addSubview scrollview];

    for (int i = 0; i<10; i++) {
        AnimalView *newAnimal = [[AnimalView alloc] init];
        // customization of newAnimal
        [scrollview addSubview:newAnimal;
    }
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    UIView *hitView = touch.view;
    if ([hitView isKindOfClass:[AnimalView class]]) {
        AnimalView *animal = (AnimalView *)hitView;
        [animal doSomething];
    }
}

However, nothing happened when I clicked on the animal. When I checked the class of hitView by NSLog(@"%@", [hitView class]), it always shows UIView instead of AnimalView. Is it true that the AnimalView changed to a UIView when it is added onto the ViewController? Is there any way I can get back the original class of a custom class?

+3  A: 

It's possible that AnimalView doesn't have user interaction enabled and is ignoring the touches. Try setting [myView setUserInteractionEnabled:YES];

David Kanarek
Thanks David. I've already set the userInteractionEnabled property to YES on the AnimalView in its init method. In fact, I got a return of "UIView" when I clicked on them. But what I want is a return of "AnimalView". Thanks anyway.
Anthony Chan
+1  A: 

Does an AnimalView have UIView subviews within it? They might be the ones picking up the touch events. You could disable the user interaction of those views by inverting the method described by David on all of the subviews of your AnimalView.

Brad Larson
Thanks Brad for reminding. As I was away from my mac, I totally forgot I have one more UIView in the AnimalView. This totally solved my headache. Thanks a lot!!
Anthony Chan
+2  A: 

If you have subviews in your AnimalView, you can iterate through the superview hierarchy to see if the touch was handled by a subview of your AnimalView by using code like this:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    UIView *hitView = touch.view;

    AnimalView *animal = nil;
    while (hitView != nil) {
        if ([hitView isKindOfClass:[AnimalView class]]) {
            animal = (AnimalView *) hitView;
            break;
        }
        hitView = [hitView superview];
    }

    if (animal) {
        [animal doSomething];
    }
}
Nick Forge
Thanks for answering. But turn out it was a stupid mistake by myself. Thanks anyway!
Anthony Chan
Not a problem! I have found this technique useful when intercepting touch events on complex views (i.e. those with several subviews) where I don't have access to the sourcecode to the views, and therefore can't hack/modify their behaviour.
Nick Forge