- 监听键盘删除按钮的事件,常规做法是使用UITextField的
textField:shouldChangeCharactersInRange:replacementString:
代理方法,但是这个方法,只能监听到输入框内有内容时的删除事件,当输入框内没有内容的时候就不会再响应了。这个时候若是想要继续监听删除按钮的事件,就需要用别的办法了。
-
先说一下UITextField的代理方法
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;
当输入内容时,range.length = 0,string.length = 1;
当删除内容时,range.length = 1,string.length = 0;
通过判断string的长度是否大于0就可以确定当前的操作是输入还是删除。
-
接下来是重点:通杀一切情况,强力获取删除按钮事件(包括输入框有内容,和内容为空时)
不难发现UITextField实现了UIKeyInput协议。
NS_CLASS_AVAILABLE_IOS(2_0) @interface UITextField : UIControl <UITextInput, NSCoding, UIContentSizeCategoryAdjusting>
@protocol UITextInput <UIKeyInput>
@protocol UIKeyInput <UITextInputTraits>
这个协议中系统抛出了deleteBackward
事件,但是UITextFieldDelegate并没有将之抛出来,所以我们要做的就是把这个事件抛出来。@protocol UIKeyInput <UITextInputTraits> #if UIKIT_DEFINE_AS_PROPERTIES @property(nonatomic, readonly) BOOL hasText; #else - (BOOL)hasText; #endif - (void)insertText:(NSString *)text; - (void)deleteBackward; @end
-
实现过程
自定义一个类,继承UITextField#import <UIKit/UIKit.h> @class CJTextField; @protocol CJTextFieldDeleteDelegate <NSObject> - (void)cjTextFieldDeleteBackward:(CJTextField *)textField; @end @interface CJTextField : UITextField @property (nonatomic,weak)id <CJTextFieldDeleteDelegate>cj_delegate; @end
在自定义CJTextField类中通过代理将
deleteBackward
事件抛出。#import "CJTextField.h" @implementation CJTextField - (void)deleteBackward { [super deleteBackward]; if ([self.cj_delegate respondsToSelector:@selector(cjTextFieldDeleteBackward:)]) { [self.cj_delegate cjTextFieldDeleteBackward:self]; } } @end
这样,我们在用到的地方通过监听
cjTextFieldDeleteBackward:
代理方法,就可以捕获到软键盘的删除按钮事件了。如果只想在输入框内容为空时才让这个方法响应,那么在
deleteBackward
方法中进行过滤即可。- (void)deleteBackward { if ([self.text length] == 0) { if ([self.cj_delegate respondsToSelector:@selector(cjTextFieldDeleteBackward:)]) { [self.cj_delegate cjTextFieldDeleteBackward:self]; } } [super deleteBackward]; }
注意:这里
super
放在后面,不然的话,当输入框内容长度为1的时候,点击删除按钮,会提前抛出deleteBackward事件。
-
然鹅,到这里还有例外,在iOS8.0到iOS8.2的系统中你会发现,
deleteBackward
方法不响应了!!!但是iOS8之前和iOS8.3及之后是可以响应的。这可咋办,别急,添加下面代码就好了。- (BOOL)keyboardInputShouldDelete:(UITextField *)textField { BOOL shouldDelete = YES; if ([UITextField instancesRespondToSelector:_cmd]) { BOOL (*keyboardInputShouldDelete)(id, SEL, UITextField *) = (BOOL (*)(id, SEL, UITextField *))[UITextField instanceMethodForSelector:_cmd]; if (keyboardInputShouldDelete) { shouldDelete = keyboardInputShouldDelete(self, _cmd, textField); } } BOOL isIos8 = ([[[UIDevice currentDevice] systemVersion] intValue] == 8); BOOL isLessThanIos8_3 = ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.3f); if (![textField.text length] && isIos8 && isLessThanIos8_3) { [self deleteBackward]; } return shouldDelete; }
这样,在iOS8-8.2的系统中,如果输入框没有内容,调用deleteBackward抛出UITextField删除按钮事件。
注意:在iOS8-8.2系统中虽然
deleteBackward
不响应,但是仍然需要调用super
方法,避免丢失继承的代码。终于结束了,我们获取到了键盘的删除事件,需求中需要做的事情,就可以在代理方法中做了。是不是超级简单呢,希望对你有用。