Обнаружение обратного пространства в пустом поле UITextField


есть ли способ определить, когда Backspace/удалить клавиша нажата на клавиатуре iPhone на UITextField пустой? Я хочу знать, когда Backspace нажимается только если UITextField пусто.


основываясь на предложении @Alex Reynolds в комментарии, я добавил следующий код при создании моего текстового поля:

[[NSNotificationCenter defaultCenter] addObserver:self
          selector:@selector(handleTextFieldChanged:)
              name:UITextFieldTextDidChangeNotification
            object:searchTextField];

данное уведомление получил (handleTextFieldChanged функция вызывается), но все же не тогда, когда я нажимаю Backspace введите в пустое поле. Есть идеи?


кажется, есть некоторая путаница вокруг этого вопроса. Я хочу получить уведомление, когда Backspace клавиша нажата. Вот и все. Но решение должно также работать, когда UITextField уже пуст.

23 103

23 ответа:

Это может быть длинный выстрел, но это может сработать. Попробуйте установить текст текстового поля на символ пробела нулевой ширины \u200B. Когда backspace нажимается на текстовое поле, которое кажется пустым, оно фактически удалит ваше пространство. Затем вы можете просто вставить на место.

может не работать, если пользователю удается переместить курсор в левую часть пространства.

Swift 4:


подкласс UITextField:

// MyTextField.swift
import UIKit

protocol MyTextFieldDelegate {
    func textFieldDidDelete()
}

class MyTextField: UITextField {

    var myDelegate: MyTextFieldDelegate?

    override func deleteBackward() {
        super.deleteBackward()
        myDelegate?.textFieldDidDelete()
    }

}

реализация:

// ViewController.swift

import UIKit

class ViewController: UIViewController, MyTextFieldDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        // initialize textField
        let input = MyTextField(frame: CGRect(x: 50, y: 50, width: 150, height: 40))

        // set viewController as "myDelegate"
        input.myDelegate = self

        // add textField to view
        view.addSubview(input)

        // focus the text field
        input.becomeFirstResponder()
    }

    func textFieldDidDelete() {
        print("delete")
    }

}

Цель-C:


подкласс UITextField:

//Header
//MyTextField.h

//create delegate protocol
@protocol MyTextFieldDelegate <NSObject>
@optional
- (void)textFieldDidDelete;
@end

@interface MyTextField : UITextField<UIKeyInput>

//create "myDelegate"
@property (nonatomic, assign) id<MyTextFieldDelegate> myDelegate;
@end

//Implementation
#import "MyTextField.h"

@implementation MyTextField

- (void)deleteBackward {
    [super deleteBackward];

    if ([_myDelegate respondsToSelector:@selector(textFieldDidDelete)]){
        [_myDelegate textFieldDidDelete];
    }
}

@end

теперь просто добавьте MyTextFieldDelegate на UIViewController и установить UITextFieldsmyDelegate до self:

//View Controller Header
#import "MyTextField.h"

//add "MyTextFieldDelegate" to you view controller
@interface ViewController : UIViewController <MyTextFieldDelegate>
@end

//View Controller Implementation
- (void)viewDidLoad {
    //initialize your text field
    MyTextField *input = 
     [[MyTextField alloc] initWithFrame:CGRectMake(0, 0, 70, 30)];

    //set your view controller as "myDelegate"
    input.myDelegate = self;

    //add your text field to the view
    [self.view addSubview:input];
}

//MyTextField Delegate
- (void)textFieldDidDelete {
    NSLog(@"delete");
}

Обновление: См.JacobCaraballo это!--10--> для примера, который переопределяет -[UITextField deleteBackward].

проверить UITextInput, в частности UIKeyInput есть deleteBackward метод это всегда вызывается при нажатии клавиши delete. Если вы делаете что-то простое, то вы можете рассмотреть только подклассы UILabel и заставить его соответствовать UIKeyInput протокол, как это сделано SimpleTextInput а это iPhone UIKeyInput пример. Примечание: UITextInput и его родственники (в том числе UIKeyInput) доступны только в iOS 3.2 и выше.

код ниже:

@interface MyTextField : UITextField
@end

@implementation MyTextField

- (void)deleteBackward
{
    [super deleteBackward];

    //At here, you can handle backspace key pressed event even the text field is empty
}

@end

наконец, не забудьте изменить свойство пользовательского класса текстового поля на "MyTextField"

Я создал другой способ проще, чем subclass решение. Даже его немного странно, но он работает нормально.

- (BOOL)textView:(UITextView *)textView 
        shouldChangeTextInRange:(NSRange)range 
        replacementText:(NSString *)text
{
    const char * _char = [text cStringUsingEncoding:NSUTF8StringEncoding];
    int isBackSpace = strcmp(_char, "\b");

    if (isBackSpace == -8) {
       // is backspace
    }

    return YES;
}

это немного странно для результата сравнения -8. Может быть, я ошибусь в какой-то момент C Programming. Но его правильная работа ;)

быстрая реализация:

import UIKit

protocol PinTexFieldDelegate : UITextFieldDelegate {
    func didPressBackspace(textField : PinTextField)
}

class PinTextField: UITextField {

    override func deleteBackward() {
        super.deleteBackward()

        // If conforming to our extension protocol
        if let pinDelegate = self.delegate as? PinTexFieldDelegate {
            pinDelegate.didPressBackspace(self)
        }
    }
}

попробовать delegate

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

затем проверить, если range.length == 1 который, кажется, имеет место, когда backspace - Это хит.

пожалуйста, используйте ниже код это поможет вам обнаружить клавиатуру удалить ключ, даже если вы текстовое поле пусто.

Цель C :

- (BOOL)keyboardInputShouldDelete:(UITextField *)textField { return YES; }

Swift:

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

ответ Никласа Альвеуса помог мне с аналогичной проблемой

я ограничивал вход в определенный набор символов, но он игнорировал обратные пространства. Так что я его проверил range.length == 1 перед обрезкой NSString. Если это правда, я просто возвращаю строку и не обрезаю ее. Смотрите ниже

 - (BOOL) textField:(UITextField *)textField 
          shouldChangeCharactersInRange:(NSRange)range 
          replacementString:(NSString *)string
 {
     NSCharacterSet *nonNumberSet = 
      [[NSCharacterSet characterSetWithCharactersInString:@"0123456789."] 
         invertedSet];

    if (range.length == 1) {
       return string;
    }
    else {
       return ([string stringByTrimmingCharactersInSet:nonNumberSet].length > 0);
    }   
 }

для тех, у кого есть проблемы с ответ Якоба я реализовал свой подкласс textfield следующим образом, и он отлично работает!

#import <UIKit/UIKit.h>

@class HTTextField;

@protocol HTBackspaceDelegate <NSObject>

@optional
- (void)textFieldDidBackspace:(HTTextField*)textField;
@end

@interface HTTextField : UITextField<UIKeyInput>

@property (nonatomic, assign) id<HTBackspaceDelegate> backspaceDelegate;

@end


#import "HTTextField.h"

@implementation HTTextField

- (void)deleteBackward {
    [super deleteBackward];
    if ([self.backspaceDelegate respondsToSelector:@selector(textFieldDidBackspace:)]){
        [self.backspaceDelegate textFieldDidBackspace:self];
    }
}

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

    if (![textField.text length] && [[[UIDevice currentDevice] systemVersion] intValue] >= 8) {
        [self deleteBackward];
    }

    return shouldDelete;
}

@end

да, используйте ниже метод для обнаружения backspace, когда текстовое поле пусто.

нужно добавить UITextFieldDelegate

yourTextField.делегат = self (ОБЯЗАТЕЛЬНО ТРЕБУЕТСЯ)

Swift:

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

Цель C:

- (BOOL)keyboardInputShouldDelete:(UITextField *)textField { 
    return YES; 
}

лучшее использование, которое я нашел для обнаружения backspace, - это обнаружение, когда пользователь нажал backspace в пустом UITextField. Например, если у вас есть "пузырчатые" получатели в почтовом приложении, когда вы нажмете backspace в UITextField, он выбирает последнего "пузырчатого" получателя.

это можно сделать аналогично ответу Якоба Карабальо. Но в ответе Якоба, если UITextField имеет один символ слева, когда вы нажмете backspace, к моменту получения сообщения делегата, UITextField уже будет пустым, так что вы эффективно обнаруживаете backspace в текстовом поле, содержащем не более одного символа.

на самом деле, если вы хотите обнаружить backspace на UITextField С ровно нулевыми символами (пустыми), то вы должны отправить сообщение в delegate перед вызовом super deleteBackward. Например:

#import "MyTextField.h"

//Text field that detects when backspace is hit with empty text
@implementation MyTextField

#pragma mark - UIKeyInput protocol
-(void)deleteBackward
{
  BOOL isTextFieldEmpty = (self.text.length == 0);
  if (isTextFieldEmpty) {
    if ([self.delegate 
         respondsToSelector:@selector(textFieldDidHitBackspaceWithEmptyText:)]) {

        [self.delegate textFieldDidHitBackspaceWithEmptyText:self];
        }
    }
    [super deleteBackward];
}
@end

интерфейс для такого текстового поля будет выглядеть примерно так:

@protocol MyTextFieldDelegate;

@interface MyTextField : UITextField
@property(nonatomic, weak) id<MyTextFieldDelegate> delegate;
@end

@protocol MyTextFieldDelegate <UITextFieldDelegate>
@optional
-(void)textFieldDidHitBackspaceWithEmptyText:(MyTextField *)textField;
@end

в iOS 6 метод deleteBackward вызывается в поле UITextField при нажатии кнопки backspace, в том числе при пустом поле. Таким образом, вы можете подкласс UITextField и предоставить свою собственную реализацию deleteBackward (вызывая супер также.)

Я все еще поддерживаю iOS 5, хотя мне понадобится комбинация ответа Эндрю и этого.

:) только для названия "Detect backspace", где я использую UIKeyboardTypeNumberPad.

Я также встречаю тот же вопрос сегодня вечером, и ниже мой код, чтобы узнать это:

- (BOOL)textField:(UITextField *)textField 
        shouldChangeCharactersInRange:(NSRange)range 
        replacementString:(NSString *)string
{
    NSLog([NSString stringWithFormat:@"%d", [string length]]);
}

потому что с UIKeyboardTypeNumberPad, пользователь может вводить только номер или backspace, поэтому, когда длина строки равна 0, это должен быть ключ backspace.

надеюсь, что выше будет делать некоторую помощь.

вместо того, чтобы пытаться предварительно построить то, что будет в текстовом поле или выяснить, какой специальный символ был введен в shouldChangeCharactersInRange способ, я бы предложил сделать следующее:

[self performSelector:@selector(manageSearchResultsDisplay) 
           withObject:nil 
           afterDelay:0];

Это позволяет вызвать метод непосредственно после завершения текущей операции. Что здорово в этом, так это то, что к моменту его завершения измененное значение уже будет в UITextField. В этот момент Вы можете просто проверить его длину и/или проверить на основе того, что там.

подкласс UITextField не работал для меня на iOS 8.3, deleteBackward никогда не вызывался.

вот решение, которое я использовал, работает на всех версиях iOS 8 и должен работать на других версиях iOS, а также

for textField in textFields {
            textField.text = " "
}

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        if string == "" && textField.text == " "   {
            // Do stuff here
            return false
        }
        return true
}

In .h Файл Добавить делегат UIKeyInput

- (BOOL)keyboardInputShouldDelete:(UITextField *)textField {

if ([textField isEqual:_txtFirstDigit]) {

}else if([textField isEqual:_txtSecondDigit]) {
    [_txtFirstDigit becomeFirstResponder];

}else if([textField isEqual:_txtThirdDigit]) {
    [_txtSecondDigit becomeFirstResponder];

}else if([textField isEqual:_txtFourthDigit]) {
    [_txtThirdDigit becomeFirstResponder];
}
return YES;
}   

улучшенное форматирование

я реализовал аналогичное решение с незначительными улучшениями, которые скажут мне, что если текстовое поле имеет какое-либо значение, пока пользователь нажал backspace. Это полезно для моего случая, когда я должен сосредоточиться только на другом текстовом поле, если текстовое поле пустое, когда клавиша нажата.

protocol MyTextFieldDelegate : UITextFieldDelegate {
    func textFieldDidDelete(textField: MyTextField, hasValue: Bool)
}

override func deleteBackward() {
    let currentText = self.text ?? ""
    super.deleteBackward()
    let hasValue = currentText.isEmpty ? false : true
    if let delegate = self.delegate as? MyTextFieldDelegate {
        delegate.textFieldDidDelete(textField: self, hasValue: hasValue)
    }
}

используя метод делегата текстового поля:

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

добавить следующий код в выше метод для обнаружения события удаления

if(textField == YourTextField)
{
    if ([string length] == 0 && range.length > 0)
    {
        // Your Code after deletion of character
    }
}

чтобы все было просто, вот единственное условие, которое нужно проверить

     if (range.length==1)
+ (BOOL)detectBackspaceOnly:(NSString *)string
{
    for(int i=0 ; i<string.length ; i++){
        unichar caract = [string characterAtIndex:i];
        if(caract != ' ' && caract != '\n')
            return NO;
    }

    return YES;
}

что-то вроде этого:

- (BOOL)textField:(UITextField *)textField 
        shouldChangeCharactersInRange:(NSRange)range 
        replacementString:(NSString *)string       
{  
    if (![text hash] && ![textField.text length])  
        [self backspaceInEmptyTextField];  
}

конечно хэш для одной символьной строки.

на UITextViewDelegate:

- (BOOL)               textView:(UITextView *)textView 
        shouldChangeTextInRange:(NSRange)range 
                replacementText:(NSString *)text
{
    if(text isEqualToString:@"");
    {
        NSLog(@"press backspace.");
    }
}

он работает нормально для меня.

обновление для китайского упрощенного пиньинь и китайского рукописного ввода:

- (BOOL)               textView:(UITextView *)textView 
        shouldChangeTextInRange:(NSRange)range 
                replacementText:(NSString *)text
{
    if (range.length > 0 && [text isEqualToString:@""]) {
        NSLog(@"press Backspace.");
    }
    return YES;
}

база на документе сказано:

"если пользователь нажимает deleteKey длина диапазона 1 и пустой строковый объект, который заменяет один символ."