hachinoBlog

hachinobuのエンジニアライフ

iOS5でaddGestureRecognizerしたViewの上にUIButtonをaddSubViewした場合にボタンを押下してもEventが呼ばれない

題名の通りaddGestureRecognizerしたViewにUIButtonをaddSubviewした際、iOS5系ではUIButtonを押下してもEventが呼ばれずUITapGestureRecognizerにフックされてしまった。

問題が起きるコード

#import "ViewController.h"
#import "AppDelegate.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    //UITapGestureRecognizerを設置
    UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
    gesture.numberOfTapsRequired = 1;
    [self.view addGestureRecognizer:gesture];
    
    //Button
    UIButton *button = [[UIButton alloc] initWithFrame:(CGRect) {CGPointZero, CGSizeMake(100, 50)}];
    AppDelegate *app = [[UIApplication sharedApplication] delegate];
    button.center = app.window.center;
    [button setTitle:@"Button" forState:UIControlStateNormal];
    button.titleLabel.textColor = [UIColor whiteColor];
    button.backgroundColor = [UIColor blueColor];
    [button addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)handleSingleTap:(id)sender
{
    NSLog(@"handleSingleTap");
}

- (void)buttonAction:(id)sender
{
    NSLog(@"buttonAction");
}

@end

サンプル画像

このようにUIButtonを押下しても出力がhandleSingleTapになってしまう。 iOS5系でこの現象を回避するにはUIButtonにaddTargetでなくUITapGestureRecognizerのinitWithTargetでインスタンスを作ってUIButtonにaddGestureRecognizerしてやればよい。

回避するコード

#import "ViewController.h"
#import "AppDelegate.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    //UITapGestureRecognizerを設置
    UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
    gesture.numberOfTapsRequired = 1;
    [self.view addGestureRecognizer:gesture];
    
    //Button
    UIButton *button = [[UIButton alloc] initWithFrame:(CGRect) {CGPointZero, CGSizeMake(100, 50)}];
    AppDelegate *app = [[UIApplication sharedApplication] delegate];
    button.center = app.window.center;
    [button setTitle:@"Button" forState:UIControlStateNormal];
    button.titleLabel.textColor = [UIColor whiteColor];
    button.backgroundColor = [UIColor blueColor];
//    [button addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
    //addTargetでなくUITapGestureRecognizerを設置する
    UITapGestureRecognizer *btnGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(buttonAction:)];
    gesture.cancelsTouchesInView = NO;
    [button addGestureRecognizer:btnGesture];
    [self.view addSubview:button];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)handleSingleTap:(id)sender
{
    NSLog(@"handleSingleTap");
}

- (void)buttonAction:(id)sender
{
    NSLog(@"buttonAction");
}

@end

サンプル画像

これでUIButtonを押下した際にbuttonActionメソッドが呼ばれるようになった。 早くiOS5系切りたい。でも初代iPadがぁ。。