如何检测iOS 8中的UITextField的删除键?

我已经子类UITextField并实现了UIKeyInput协议的deleteBackward方法来检测被按下的退格。 这适用于iOS 7,但不适用于iOS 8。

当我按下退格键时,不会在UITextField上调用deleteBackward。

我检查了文档和发行说明,没有指出为什么会发生这种情况。 任何指针?

您必须在github上查找MBContactPicker的示例。 通过我testing的iOS8上的Backspacebutton删除MBContactPicker中的联系人。 它工作很大! 你可以用它作为例子。

MBContactPicker的作者使用下一个方法:当UITextField必须变为空(或者在空的时候调用becomeFirstResponder之前),他在那里保存单个的空白符号。 然后当你按退格button(当焦点被设置为你的UITextField的文本的结尾),方法

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)text 

将工作。 在里面你必须使用这样的检查:

 NSString *resultString = [textField.text stringByReplacingCharactersInRange:range withString:text]; BOOL isPressedBackspaceAfterSingleSpaceSymbol = [text isEqualToString:@""] && [resultString isEqualToString:@""] && range.location == 0 && range.length == 1; if (isPressedBackspaceAfterSingleSpaceSymbol) { // your actions for deleteBackward actions } 

所以,你必须始终控制,UITextField包含单个空格。

这不是黑客。 所以,用户不会注意到一些行为被改变了

很多人一直在说这是一个错误,但是因为这个问题在GM中依然存在,我开始认为这可能是逻辑上的一个变化。 有了这个说法,我为我的应用程序编写了一些代码,并在iOS 7-8上进行了testing。

将以下方法添加到您的UITextField子类。

 - (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; } 

这个代码稍微在私有API的红线之前,但是你应该没有问题使用它。 我的这个代码的应用程序是在应用程序商店。

为了解释一下,正在调用这个方法的超级实现,以避免丢失代码。 如果没有文字,iOS版本介于8-8.2之间,则打电话后删除。

编辑 :1/22/15

子类UITextField-deleteBackward方法也可能是有帮助的。 这修复了一些有条件的错误。 一个如果你使用自定义键盘。 下面是方法的一个例子。

 - (void)deleteBackward { BOOL shouldDismiss = [self.text length] == 0; [super deleteBackward]; if (shouldDismiss) { if ([self.delegate respondsToSelector:@selector(textField:shouldChangeCharactersInRange:replacementString:)]) { [self.delegate textField:self shouldChangeCharactersInRange:NSMakeRange(0, 0) replacementString:@""]; } } } 

编辑 :4/13/15

As @ Gee.E评论说,iOS 8.3已经解决了这个问题。 代码已更新以反映更改。

通过实现UITextField委托方法,您可以通过使用退格来检测用户何时删除文本:

 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { if (range.length==1 && string.length==0) NSLog(@"backspace tapped"); return YES; } 

Swift 2.2:

 func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool { if text == "" { print("Backspace has been pressed") } return true } 

在iOS8中,一些自定义键盘会删除整个单词,所以只需检查string.length即可。

 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { if (string.length==0) { //Delete any cases if(range.length > 1){ //Delete whole word } else if(range.length == 1){ //Delete single letter } else if(range.length == 0){ //Tap delete key when textField empty } } return YES; } 

Swift 2.0版本用于检测基于BackSpace的删除, 从almas引用代码发布

 //For Detecting Backspace based Deletion of Entire Word in TextField func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { if (range.length == 1 && string.isEmpty){ print("Used Backspace") } return true } 
 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { const char * _char = [string cStringUsingEncoding:NSUTF8StringEncoding]; int isBackSpace = strcmp(_char, "\b"); if (isBackSpace == -8) { NSLog(@"Backspace was pressed"); } return YES; } 

基本上这个方法检测你正在按哪个button(或刚刚按下)。 这个input作为一个NSString。 我们将这个NSString转换为C chartypes,然后将它与传统的退格字符(\ b)进行比较。 那么如果这个strcmp等于-8,我们可以检测到它是一个退格。

迅捷2:

 if (string.characters.count == 0 && range.length == 1) { return true } 

你应该像这样使用string.characters.count