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

时间:2014-08-18 20:08:17

标签: ios uitextfield ios8 uitextfielddelegate uikeyinput

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

当我按退格键时,

不再在UITextField上调用deleteBackward。

我已经检查了文档和发行说明,没有任何指出可能发生这种情况的原因。有什么指针吗?

10 个答案:

答案 0 :(得分: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的红线之前,但是使用它时应该没有问题。我的应用程序使用此代码在应用程序商店中。

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

编辑:2015年1月22日

继承子类-deleteBackward的{​​{1}}方法也可能有所帮助。这修复了一些有条件的错误。一种是如果你使用自定义键盘。这是该方法的一个例子。

UITextField

编辑:4/13/15

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

答案 1 :(得分:22)

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

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

    return YES;
}

答案 2 :(得分:12)

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

MBContactPicker的作者使用next方法:当UITextField必须为空时(或者在它为空时调用becomeFirstResponder之前),他在那里保存单个空格符号。然后当您按Backspace按钮时(当焦点设置为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包含单个空格。

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

答案 3 :(得分:5)

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

答案 4 :(得分:5)

Swift 2.2:

filters: [
        {
            property: 'type',
            operator: '=',
            value: 'recorder'
        },
        {
            property: 'number',
            operator: '=',
            value: '{number.value}'
        }

答案 5 :(得分:1)

用于检测基于BackSpace的删除的Swift 2.0版本,referencing code post from 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
}

答案 6 :(得分:1)

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

string:指定范围的替换字符串。在键入过程中,此参数通常仅包含键入的单个新字符,但是如果用户要粘贴文本,则它可能包含更多字符。删除一个或多个字符,替换字符串为空。”

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

这里的许多其他答案都使用了相同的逻辑,而没有引用文档,因此希望从源头上正确地使它使人们更习惯使用它。

答案 7 :(得分: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,我们可以将其检测为退格。

答案 8 :(得分:0)

swift 2:

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

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

答案 9 :(得分:0)

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

按下删除键时会调用此功能