Ryan
Ryan

Reputation: 39

UIButton not working. Not first responder or is hiding behind view

My UIButton doesn't respond. I think it is behind the UIView or that it is not the first responder. I made a custom view which subclass is MKAnnotationView. Maybe this is a part of the problem. I also tried to use userInteractionEnabled, but no luck. Anyone had the same issue?

- (id)initWithAnnotation:(id)annotation reuseIdentifier:(NSString *)reuseIdentifier{   
self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];

// Create selected and un-selected pin images
_normalPin = [UIImage imageNamed:@"map_pin.png"];
_selectedPin = [UIImage imageNamed:@"selected_map_pin.png"];

// Set current pin to unselected image
self.image = _normalPin;

// cast annotation an our expected BLAnnotation

Annotation *blAnnotation = (Annotation *)annotation;

// create title label and size to text

_titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 5, 280, 20)];
_titleLabel.text = blAnnotation.title;
_titleLabel.textAlignment = UITextAlignmentLeft;
_titleLabel.font = [UIFont fontWithName:@"HelveticaNeue-Bold" size:13];
_titleLabel.textColor = [UIColor whiteColor];
_titleLabel.shadowColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:.7];
_titleLabel.shadowOffset = CGSizeMake(0, -1.0);
_titleLabel.backgroundColor = [UIColor clearColor];
_titleLabel.lineBreakMode = UILineBreakModeWordWrap;
_titleLabel.numberOfLines = 3;

CGSize titleLabelSize = [blAnnotation.title sizeWithFont: _titleLabel.font constrainedToSize: CGSizeMake(280, 600) lineBreakMode: _titleLabel.lineBreakMode];
_titleLabel.frame = CGRectMake(_titleLabel.frame.origin.x, _titleLabel.frame.origin.y, 280, titleLabelSize.height);

// create subtitle label and size to text

_subtitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, _titleLabel.frame.size.height + 8, 280, 20)];
_subtitleLabel.text = blAnnotation.subtitle;
_subtitleLabel.textAlignment = UITextAlignmentLeft;
_subtitleLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:11];
_subtitleLabel.textColor = [UIColor whiteColor];
_subtitleLabel.shadowColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:.7];
_subtitleLabel.shadowOffset = CGSizeMake(0, -1.0);
_subtitleLabel.backgroundColor = [UIColor clearColor];
_subtitleLabel.lineBreakMode = UILineBreakModeWordWrap;
_subtitleLabel.numberOfLines = 4;

CGSize subtitleLabelSize = [blAnnotation.subtitle sizeWithFont: _subtitleLabel.font constrainedToSize: CGSizeMake(235, 600) lineBreakMode: _subtitleLabel.lineBreakMode];
_subtitleLabel.frame = CGRectMake(_subtitleLabel.frame.origin.x, _subtitleLabel.frame.origin.y, subtitleLabelSize.width, subtitleLabelSize.height);

// create custom button
_infoButton = [UIButton buttonWithType:UIButtonTypeCustom];
_infoButton.frame = CGRectMake(0, _titleLabel.frame.size.height + _subtitleLabel.frame.size.height + 80, 175, 50);
//_infoButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
//_infoButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;

//[_infoButton setImage:[UIImage imageNamed:@"more_info.png"] forState:UIControlStateNormal];
[_infoButton addTarget:self action:@selector(pressButton:) forControlEvents:UIControlEventTouchUpInside];

// create callout view to be shown once a annotation view is selected

_calloutView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, _titleLabel.frame.size.height + _subtitleLabel.frame.size.height + _infoButton.frame.size.height + 5)];
_calloutView.hidden = YES;
_calloutView.userInteractionEnabled = YES;
[self addSubview:_calloutView];

// create rounded rect background and size to text

UIImageView *backgroundRect = [[UIImageView alloc] initWithFrame: CGRectMake(0, 0, _calloutView.frame.size.width, _calloutView.frame.size.height)];
//[backgroundRect setAlpha:0.8];
//[backgroundRect setOpaque:NO];
[backgroundRect.image drawInRect:_calloutView.frame];

UIGraphicsBeginImageContext(backgroundRect.frame.size);

CGContextRef ctx = UIGraphicsGetCurrentContext();
CGRect frame = _calloutView.bounds;
[[UIColor colorWithRed:.2 green:.2 blue:.2 alpha:1] set];
CGPathRef roundedRectPath = [self roundedRectPath:frame radius:5];
CGContextAddPath(ctx, roundedRectPath);
CGContextFillPath(ctx);
CGPathRelease(roundedRectPath); 

backgroundRect.userInteractionEnabled = YES;
backgroundRect.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

[_calloutView addSubview:backgroundRect];
[_calloutView addSubview:_titleLabel];
[_calloutView addSubview:_subtitleLabel];
[_calloutView addSubview:_infoButton];

// position callout above pin

_calloutView.frame = CGRectMake(-140, -_calloutView.frame.size.height+10, _calloutView.frame.size.width, _calloutView.frame.size.height);

backgroundRect = nil;

return self;

}

Upvotes: 1

Views: 639

Answers (2)

Sanzio Angeli
Sanzio Angeli

Reputation: 3942

My guess is that your button is pointing to itself as the target. If the button is not the first responder and it is tapped, its target function is not called in the above scenario. I fixed my similar issue by using lazy var to declare the UIButton in Swift 4 Xcode 9, pointing the target to the parent view / view controller.

// Sets target to parent view or view controller
// someFunction is called even if the button is not the first responder when tapped
lazy var nextCreateButton: UIButton = {
    let button = UIButton(type: .system)
    button.addTarget(self, action: #selector(someFunction), for: .touchUpInside)
    return button
}()

// Sets target to the button itself
// someFunction is not called when the button is not the first responder
let nextCreateButton: UIButton = {
    let button = UIButton(type: .system)
    button.addTarget(self, action: #selector(someFunction), for: .touchUpInside)
    return button
}()

Upvotes: 1

Eren Beşel
Eren Beşel

Reputation: 1057

Try using [self addSubview:_calloutView] after you add your button and your lables to *_calloutView* as subviews, not before.

Let me know how it turns out

Upvotes: 0

Related Questions