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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25371254/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 01:54:50  来源:igfitidea点击:

How to detect delete key on an UITextField in iOS 8?

iosuitextfieldios8uitextfielddelegateuikeyinput

提问by VNVN

I have subclassed UITextField and implemented the UIKeyInput protocol's deleteBackward method to detect backspace being pressed. This works fine on iOS 7 but not on iOS 8.

我已经继承了 UITextField 并实现了 UIKeyInput 协议的 deleteBackward 方法来检测被按下的退格。这在 iOS 7 上运行良好,但在 iOS 8 上不起作用。

deleteBackward is not called on the UITextField anymore when I press the backspace key.

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

I've checked the documentation and the release notes and nothing points to the reason why this could happen. Any pointers?

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

采纳答案by iVader

You must look an example for MBContactPickeron github. Deletion of contacts at MBContactPicker via Backspace button on iOS8 tested by me. And it works greatly! You can use its as example.

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

Author of MBContactPicker use next method: When UITextField must become empty (or before call becomeFirstResponder when it is empty), he save single whitespace symbol there. And then when you press Backspace button (when focus was set to end of text of your UITextField), method

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

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

will work. Inside it you must use check like this:

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

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
}

So, you must always control that UITextField contains single whitespace.

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

This is not hack. So, user willn't noticed about some behaviour was changed

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

回答by cnotethegr8

A lot of people have been saying this is a bug, but being that this problem still exists in the GM I'm starting to think it might be a change in logic. With that said, I wrote this bit of code for my app and have tested it on iOS 7-8.

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

Add the following method to your UITextFieldsubclass.

将以下方法添加到您的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;
}

This code is slightly before the red line of private API's, however you should have no problem using it. My app with this code is in the app store.

这段代码略在私有 API 的红线之前,但是您使用它应该没有问题。我使用此代码的应用程序在应用程序商店中。

To explain a little, were calling the super implementation of this method to avoid losing code. After were going to call -deleteBackwardif there is no text and the iOS version is between 8-8.2.

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

EDIT: 1/22/15

编辑:1/22/15

It also might be helpful to subclass the -deleteBackwardmethod of your subclassed UITextField. This fixes a few conditional bugs. One being if you use a custom keyboard. Heres an example of the method.

对子类的-deleteBackward方法进行子类化也可能会有所帮助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:@""];
        }
    }
}

EDIT: 4/13/15

编辑:4/13/15

As @Gee.E commented, iOS 8.3 has fixed this issue. The code has been updated to reflect the changes.

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

回答by almas

You can detect when user deletes text by using backspace by implementing UITextField delegate method:

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

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

    return YES;
}

回答by LE SANG

In iOS8, some custom keyboards delete whole word, so only check string.length is OK.

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

回答by W?odzimierz Wo?niak

Swift 2.2:

斯威夫特 2.2:

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

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

    return true
}

回答by Brian Sachetta

This does not explicitly answer the original question but worth nothing that in the documentation for textField(_:shouldChangeCharactersIn:replacementString:), it says:

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

"string: The replacement string for the specified range. During typing, this parameter normally contains only the single new character that was typed, but it may contain more characters if the user is pasting text. When the user deletes one or more characters, the replacement string is empty."

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

Thus, we can detect backspaces in a UITextFieldDelegateif we implement textField(_:shouldChangeCharactersIn:replacementString:)and check if the length of stringis 0.

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

A lot of other answers here have used this same logic without referencing the documentation so hopefully getting it right from the source makes people more comfortable using it.

这里的许多其他答案都使用了相同的逻辑,而没有参考文档,因此希望从源头获取正确的信息可以让人们更舒适地使用它。

回答by Abhijeet

Swift 2.0 version for Detecting BackSpace based deletion, referencing code post from almas

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
}

回答by fatihyildizhan

swift 2:

快速2:

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

you should use like this string.characters.count

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

回答by Ankit Soni

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

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

This function is called when you hit delete key

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

回答by mars

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

}

Basically this method detects which button you are pressing (or have just pressed). This input comes in as an NSString. We convert this NSString to a C char type and then compare it to the traditional backspace character (\b). Then if this strcmp is equal to -8, we can detect it as a backspace.

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