Jason Silberman Jason Silberman - 1 month ago 19
Objective-C Question

UIButton targets not working if a UIView is added as a subview

I have a

UIButton
. It has two subviews. I then call:

[createButton addTarget:self action:@selector(openComposer) forControlEvents:UIControlEventTouchUpInside];


If I tap the parts of the
UIButton
that aren't covered but one of its subviews, it works fine. However if I tap one of the subviews instead, it does not trigger the action.

On both subviews, I has
.userInteractionEnabled
set to
YES
.

Both subviews are plain
UIViews
s with a
frame
and
backgroundColor
.

How can I get the tap to "pass through" the
UIView
and onto the
UIButton
?

Thanks

EDIT: I need to use UIControlEvents because I need UIControlEventTouchDown.

EDIT 2:

Here is the code for the button.

@interface CreateButton ()

@property (nonatomic) Theme *theme;
@property (nonatomic) UIView *verticle;
@property (nonatomic) UIView *horizontal;
@property (nonatomic) BOOL mini;

@end

@implementation CreateButton

#pragma mark - Accessors

- (UIView *)verticle {
if (! _verticle) {
_verticle = [[UIView alloc] init];
_verticle.backgroundColor = [self.theme colorForKey:@"createButtonPlusBackgroundColor"];
_verticle.userInteractionEnabled = NO;
}
return _verticle;
}

- (UIView *)horizontal {
if (! _horizontal) {
_horizontal = [[UIView alloc] init];
_horizontal.backgroundColor = [self.theme colorForKey:@"createButtonPlusBackgroundColor"];
_verticle.userInteractionEnabled = NO;
}
return _horizontal;
}

#pragma mark - Init

- (instancetype)initWithTheme:(Theme *)theme frame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
_theme = theme;

self.layer.cornerRadius = roundf(frame.size.width / 2);
self.layer.shadowColor = [UIColor blackColor].CGColor;
self.layer.shadowOpacity = .1f;
self.layer.shadowOffset = CGSizeZero;
self.layer.shadowRadius = 15.f;
self.backgroundColor = [self.theme colorForKey:@"createButtonBackgroundColor"];

[self addSubview:self.verticle];
[self addSubview:self.horizontal];

[self addTarget:self action:@selector(animate) forControlEvents:UIControlEventTouchDown];
[self addTarget:self action:@selector(animate) forControlEvents:UIControlEventTouchUpInside];
[self addTarget:self action:@selector(animate) forControlEvents:UIControlEventTouchUpOutside];
}
return self;
}

#pragma mark - Actions

- (void)animate {
[UIView animateWithDuration:0.2 delay:0 usingSpringWithDamping:0.4 initialSpringVelocity:8 options:kNilOptions animations:^{
if (self.mini) {
self.transform = CGAffineTransformMakeScale(1.0, 1.0);
self.mini = NO;
} else {
self.transform = CGAffineTransformMakeScale(0.90, 0.90);
self.mini = YES;
}
} completion:nil];
}

#pragma mark - UIView

- (void)layoutSubviews {
CGSize size = self.bounds.size;

NSInteger width = 3;
NSInteger verticleInset = 12;
self.verticle.frame = CGRectMake((size.width - width) / 2, verticleInset, width, size.height - (verticleInset * 2));
self.horizontal.frame = CGRectMake(verticleInset, (size.height - width) / 2, size.width - (verticleInset * 2), width);
}

@end

Answer

Set userInteractionEnabled to NO for your subviews to let touches pass through them and onto your button.

Also make sure to change _verticle.userInteractionEnabled = NO; in your lazy-loader for your horizontal property to _horizontal.userInteractionEnabled = NO; as I believe that's a typo.

Comments