iOS:关于关闭UITextfield键盘的一点研究

最近写登录界面,界面是网红脸——几个输入框,几个按钮和一个开关。

点击按钮,有时界面是不会跳转的,这时如果有键盘,让键盘 dismiss 是正常的需求,于是小小地研究了一下~~~

两种情况:

1,点击空白区域,可以通过在触摸方法中实现(这个大家都可以搜到,so,这不是我想说的)——

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

{

if (![[touches anyObject].view isKindOfClass:[UITextField class]]) {

[self.view endEditing:YES];

}

}

2,点击UIButton,UISwitch等本身可以处理响应的控件,因为Responder Chain的原因,控件的触发的事件会覆盖UIView本身的响应,所以要在这时收起键盘只能在触发事件中处理,可以在事件中加入如下代码:

[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];

即:

- (IBAction)buttonDidPress:(id)sender

{

[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];

}

这个其实也很容易搜到,所以也不是我想说的...

我想说的是如果按钮比较多,这样一个个写起来岂不是太麻烦了,虽然每个方法里只加一行代码,但看起来还是很蛋疼....

所以我想要一个所有按钮点击的时候都会走的方法,于是乎,我写了一个category,并且在category中复写了- (void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event方法,并且在该方法中resignFirstResponder,即:

- (void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event

{

NSLog(@"%s", __func__);

[super sendAction:action to:target forEvent:event];

[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];

}

注意,在该方法中一定要调用父类的这个方法,否则你的按钮就罢工了...

那我要是点击开关的时候也想要收起键盘呢?简单,因为这个方法是UIControl里面的,而且UIButton和UISwitch都是UIControl的子类,所以再照葫芦画瓢写一个UISwitch的category就ok了。

这样点击按钮和开关就都可以关掉键盘了,我蛋疼地看着两个蛋疼的category,想着如何解决这隐隐的忧伤————两个category里面的方法都是一样的,不可以写一个吗?

于是我又蛋疼地上路了,写了个UIControl的category,又复写了那个方法,满以为会不疼了,结果并不满意,Xcode出示了黄牌:Category is implementing a method which will also be implemented by its primary class。原因是这个方法是UIControl已有的,就不建议再在category中复写,这样写会导致UIControl的方法列表中有两个一样的方法签名,运行的时候会产生unexpected后果。

                                                                                      A

好吧,既然影子不让有,那我只能碰你真身了,因为我们有牛( )闪闪放光芒的runtime,我就

                                                                                      C

可以写个别的名的方法实现这个功能,并且都不再给你走自己方法的机会:

+ (void)load

{

Method originalMethod = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));

Method expectMethod = class_getInstanceMethod(self, @selector(resignFirstResponderWithOriginalAction:to:forEvent:));

method_exchangeImplementations(originalMethod, expectMethod);

}

- (void)resignFirstResponderWithOriginalAction:(SEL)action to:(id)target forEvent:(UIEvent *)event

{

NSLog(@"%s", __func__);

[self resignFirstResponderWithOriginalAction:action to:target forEvent:event];

[[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];

}

OK,大功告成,没有黄牌,键盘下来!

以上代码均已放到git上,大家有兴趣的可以看看。

不过鉴于以上需求均为鄙人遐想所求,现实中遇到较少,且以上实现方式是Universal的,为避免误伤,还是慎用的好,我这么想这么做也是为了开阔开阔思路~~

首次写文,难免有瑕疵疏漏,还望大牛提出宝贵意见,不胜感激!

你可能感兴趣的:(菜鸟成长)