`

responder chain有时不那么可靠,建议还是显式指定target

 
阅读更多

今天发现一个偶现的BUG,当点击一个UIButton时,大部分情况下,对应的ViewController可以正确捕获到此tap event。但是有时此事件会跳过ViewController,被responder chain里的最后一个responder即AppDelegate处理

一开始,我想依赖responder chain来响应点击,这样就不需要把controller传给view

[closeButton addTarget:nil action:@selector(closeButtonPressed) forControlEvents:UIControlEventTouchUpInside];

在UIViewController里,实现closeButtonPressed方法:

-(void) closeButtonPressed
{
    [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];// 在LoginViewController上调用dismiss方法
}

大部分情况下,上面的代码可以正常工作。但是却存在开头描述的那个BUG,发生的几率大概是20%,最后还是显式地设置了target,不依赖responder chain来传递事件,问题就解决了。所以,建议尽量不要依赖responder chain

不过一开始我设置target的代码写得不对:

YLSRegisterStepOneViewController *step1Controller = [[YLSRegisterStepOneViewController alloc] initWithNibName:nil bundle:nil];
YLSRegisterStepOneView *step1View = [[YLSRegisterStepOneView alloc] initWithFrame:CGRectMake(0, 0, 540, 720) OperType:operType];
step1Controller.view = step1View;
step1View.controller = step1Controller;

在UIView里:

[closeButton addTarget:self.controller action:@selector(closeButtonPressed) forControlEvents:UIControlEventTouchUpInside];

上面的代码错了。因为初始化UIView的代码,比设置controller property的代码先执行,所以等于是:

[closeButton addTarget:nil action:@selector(closeButtonPressed) forControlEvents:UIControlEventTouchUpInside];

最后修改为:

YLSRegisterStepOneViewController *step1Controller = [[YLSRegisterStepOneViewController alloc] initWithNibName:nil bundle:nil];
step1Controller.view = [[YLSRegisterStepOneView alloc] initWithFrame:CGRectMake(0, 0, 540, 720) OperType:operType Controller:step1Controller];

[closeButton addTarget:controller action:@selector(closeButtonPressed) forControlEvents:UIControlEventTouchUpInside];

在调用UIView的initWithFrame:OperType:Controller:方法时,就把UIViewController作为参数传进去,这样才正确指定了事件的target

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics