40

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

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

我已经检查了文档和发行说明,但没有任何迹象表明会发生这种情况。任何指针?

4

10 回答 10

47

很多人一直说这是一个错误,但由于这个问题仍然存在于 GM 中,我开始认为这可能是逻辑上的变化。话虽如此,我为我的应用程序编写了这段代码,并在 iOS 7-8 上对其进行了测试。

将以下方法添加到您的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 的红线之前,但是你使用它应该没有问题。我的带有此代码的应用程序位于应用程序商店中。

稍微解释一下,调用这个方法的超级实现以避免丢失代码。-deleteBackward如果没有文字并且iOS版本在8-8.2之间,之后会打电话。

编辑:15 年 1 月 22 日

-deleteBackward将 subclassed 的方法子类化也可能会有所帮助UITextField。这修复了一些条件错误。一个是如果您使用自定义键盘。这是该方法的示例。

- (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:@""];
        }
    }
}

编辑:2015 年 4 月 13 日

正如@Gee.E 评论的那样,iOS 8.3 已经解决了这个问题。代码已更新以反映更改。

于 2014-09-16T07:24:13.917 回答
23

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

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

    return YES;
}
于 2014-08-18T20:17:52.750 回答
12

您必须在 github 上查看MBContactPicker的示例。我测试了通过 iOS8 上的 Backspace 按钮删除 MBContactPicker 上的联系人。而且效果很好!您可以将其用作示例。

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

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

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

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

因此,您必须始终控制 UITextField 包含单个空格。

这不是黑客。因此,用户不会注意到某些行为已更改

于 2014-09-12T06:10:10.457 回答
7

斯威夫特 2.2:

func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {

    if text == "" {
      print("Backspace has been pressed")
    }

    return true
}
于 2016-04-18T12:40:16.220 回答
6

在 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;
}
于 2015-07-09T03:46:56.263 回答
2

这没有明确回答原始问题,但在文档中毫无价值textField(_:shouldChangeCharactersIn:replacementString:),它说:

" string:指定范围的替换字符串。在键入时,此参数通常只包含输入的单个新字符,但如果用户正在粘贴文本,则可能包含更多字符。当用户删除一个或多个字符时,替换字符串为空。”

UITextFieldDelegate因此,如果我们实现textField(_:shouldChangeCharactersIn:replacementString:)并检查长度是否string为 0 ,我们可以检测 a 中的退格。

这里的许多其他答案在没有参考文档的情况下使用了相同的逻辑,因此希望从源代码中正确获取它会使人们更舒适地使用它。

于 2018-07-27T12:54:35.373 回答
1

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
}
于 2015-10-06T06:03:04.043 回答
0
- (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;

}

基本上,此方法检测您正在按下(或刚刚按下)哪个按钮。此输入以 NSString 的形式出现。我们将此 NSString 转换为 C char 类型,然后将其与传统的退格字符 (\b) 进行比较。那么如果这个strcmp等于-8,我们就可以把它检测为退格了。

于 2015-06-16T12:16:40.737 回答
0

迅速2:

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

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

于 2015-11-18T14:17:54.083 回答
0

func keyboardInputShouldDelete(_ textField: UITextField) -> Bool { }

当您按下删除键时调用此函数

于 2020-01-08T08:56:41.123 回答