Ios – UIControl Not Receiving Touches

iosiphoneuicontroluitouch

I have a UIControl which implements the touches began method like so:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesBegan:touches withEvent:event];
    //More code goes here

This subclass of UIControl is instantiated in a view controller, it is then added as a subview to that view controller. I have a breakpoint at the touches began method of the UIControl, and the method never gets called. I've been doing some reading and it seems that the View Controller has some logic that decides whether to pass on touch events to its subviews. The strange thing is that I have a different subclass of UIControl in the same view controller, and the touch events get passed down to it when the user touches it!
Here is the full code:

.h

#import <UIKit/UIKit.h>

@interface CustomSegment : UIView
@property (nonatomic, strong) UIImageView *bgImageView;
@property (nonatomic, assign) NSInteger segments;
@property (nonatomic, strong) NSArray *touchDownImages;
@property (nonatomic, readonly, assign) NSInteger selectedIndex;
@property (nonatomic, weak) id delegate;


- (id)initWithPoint:(CGPoint)point numberOfSegments:(NSInteger)_segments andTouchDownImages:(NSArray *)_touchDownImages;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
@end

.m

#import "CustomSegment.h"

@implementation CustomSegment
@synthesize bgImageView, segments, touchDownImages, selectedIndex, delegate;

- (id)initWithPoint:(CGPoint)point
   numberOfSegments:(NSInteger)_segments
           andTouchDownImages:(NSArray *)_touchDownImages  
{  
    self = [super initWithFrame:CGRectMake(point.x, point.y, [[_touchDownImages     objectAtIndex:0] size].width, [[touchDownImages objectAtIndex:0] size].height)];
if (self)
{
    touchDownImages = _touchDownImages;
    segments = _segments;
    bgImageView = [[UIImageView alloc] initWithImage:[touchDownImages objectAtIndex:0]];
    [self addSubview:bgImageView];
}
return self;
}

- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
{
    return YES;  
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //[super touchesBegan:touches withEvent:event];
    UITouch *touch = [touches anyObject];
    float widthOfSegment = [self frame].size.width / segments;
    float bottomPoint = 0;
    float topPoint = widthOfSegment;
    for (int i = 0; i < segments; i++)
    {
        if ([touch locationInView:self].x > bottomPoint && [touch locationInView:self].x < topPoint)
        {
            [bgImageView setImage:[touchDownImages objectAtIndex:i]];
            selectedIndex = i;
            return;
        }
        else
        {
            bottomPoint = topPoint;
            topPoint += topPoint;
        }
    }
}
@end

Best Answer

tl;dr Set all subviews of the UIControl to setUserInteractionEnabled:NO. UIImageView's by default have it set to true.

Original Post

One thing I found recently is that it helps if the top-most subview of the UIControl has setUserInteractionEnabled:NO. I arrived at this because I had a UIControl subclass with a UIImageView as it's only subview and it worked fine. UIImageView has userInteractionEnabled set to NO by default.

I also had another UIControl with a UIView as it's top most subview (technically the same UIControl in a different state). I believe UIView defaults to userInteractionEnabled == YES, which precluded the events being handled by the UIControl. Settings the UIView's userInteractionEnabled to NO solved my issue.

I don't know if it's the same issue here, but maybe that will help?

-- Edit: When I say topmost view... probably set all subviews of the UIControl to setUserInteractionEnabled:NO

Related Topic