Как отключить клавиатуру при редактировании UITextField

Я знаю, что мне нужно сообщить своему UITextField об увольнении первого респондента, когда я хочу отключить клавиатуру, но я не уверен, как узнать, когда пользователь нажал клавишу «Готово» на клавиатуре. Есть ли уведомление, которое я могу посмотреть?


person kubi    schedule 08.11.2008    source источник
comment
[self.view endEditing: ДА]; в касаниях начал делегат - лучшее решение   -  person AndroidGeek    schedule 15.11.2014


Ответы (20)


Я установил делегата UITextField в свой ViewController класс.

В этом классе я реализовал этот метод следующим образом:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    [textField resignFirstResponder];
    return NO;
}
person kubi    schedule 08.11.2008
comment
См. Пример выше ... подключите, используя IntefaceBuilder, к действию на том, что вы используете в качестве контроллера ... всякий раз, когда пользователь закрывает систему ввода текста (нажимает кнопку "Готово"), это будет вызвано ... - person Jason Coco; 08.11.2008
comment
Любой из них будет работать - текстовое поле отправляет свое действие, когда пользователь нажимает клавишу Return (Done, что угодно), а также отправляет своего делегата -textFieldShouldReturn :. - person Noah Witherspoon; 08.11.2008
comment
Кстати - это также работает для UISearchBar. Например, в моем коде у меня был член IBOutlet searchBarTusb; Когда была нажата моя «клавиша возврата» (UIReturnKeySearch), - (void) searchBarSearchButtonClicked :, я помещаю инструкцию [searchBarTusb resignFirstResponder]; Также обратите внимание, что «ключ возврата» был установлен в NIB с помощью Interface Builder. - person mobibob; 04.01.2010
comment
Зачем возвращать NO вместо YES? - person Iulian Onofrei; 30.01.2019
comment
@IulianOnofrei По умолчанию кнопка возврата добавляет строку возврата и сохраняет клавиатуру на экране. Возвращая NO, вы избегаете добавления к тексту возврата строки. - person kubi; 21.02.2019
comment
Я возвращаю YES, и он не добавляет строки к тексту. - person Iulian Onofrei; 21.02.2019
comment
Это больше не работает. Вы должны отключить клавиатуру после задержки. func textFieldShouldClear(_ textField: UITextField) -> Bool { DispatchQueue.main.async { self.resignFirstResponder() } return true } - person alekop; 22.08.2019

Если вы подключите событие DidEndOnExit текстового поля к действию (IBAction) в InterfaceBuilder, оно будет отправлено, когда пользователь закрывает клавиатуру (с помощью клавиши возврата), а отправитель будет ссылкой на UITextField, вызвавшее событие.

Например:

-(IBAction)userDoneEnteringText:(id)sender
{
    UITextField theField = (UITextField*)sender;
    // do whatever you want with this text field
}

Затем в InterfaceBuilder свяжите событие DidEndOnExit текстового поля с этим действием на вашем контроллере (или с тем, что вы используете для связывания событий из пользовательского интерфейса). Каждый раз, когда пользователь вводит текст и закрывает текстовое поле, контроллеру будет отправлено это сообщение.

person Jason Coco    schedule 08.11.2008
comment
Единственное событие, которое, похоже, может сработать, - это textFieldDidEndEditing, в котором говорится, что оно отправляется только после того, как UITextField откажется от статуса первого респондента. Как я узнаю, что мне нужно отказаться от статуса первого респондента? - person kubi; 08.11.2008
comment
Прошу прощения за терминологию ... это не настоящее уведомление (событие) ... Я собираюсь отредактировать свой ответ с помощью быстрого примера и объяснения, так что посмотрите :) - person Jason Coco; 08.11.2008
comment
Чтобы прояснить этот ответ, textField отправляет событие Did End On Exit, когда вы нажимаете клавишу возврата, поэтому вам нужно связать его с вашим контроллером. Я думаю, что этот метод проще, чем тот, который я описал выше. - person kubi; 23.04.2009
comment
не могли бы вы отредактировать этот ответ, чтобы он упоминал, КАКОЕ событие нужно подключать, пожалуйста? Это явно лучше, чем установка делегата. - person Dan Rosenstark; 24.12.2010
comment
Хотите проголосовать за этот ответ, но не можете, пока в нем не будет упоминаться событие DidEndOnExit. Кто-то с правами редактирования, пожалуйста, внесите изменения, если OP этого не сделает? - person James Hart; 21.04.2011

Вы также можете создать метод в своем контроллере

 -(IBAction)editingEnded:(id)sender{
    [sender resignFirstResponder]; 
}

а затем в инспекторе подключений в IB подключите к нему событие «Did End On Exit».

person Hugo    schedule 01.05.2009
comment
Это почти неверно или, по крайней мере, не соответствует сути. Подписавшись на событие DidEndOnExit, вам не нужно вызывать resignFirstResponder. Вы можете проверить это, установив символическую точку останова на [UIResponder resignFirstResponder]. Обратите внимание, что даже если вы не вызовете resignFirstResponder, он все равно будет вызван системой. Это объясняется в превосходной книге (-ах) Мэтта Нойбурга: apeth.com/iOSBook/ - person Chris Conover; 24.04.2015

куби, спасибо. Ваш код работал. Чтобы быть явным (например, для новичков), как вы говорите, вы должны установить UITextField delegate равным ViewController, в котором находится текстовое поле. Вы можете делать это где угодно. Я выбрал viewDidLoad метод.

- (void)viewDidLoad 
{
    // sets the textField delegates to equal this viewController ... this allows for the keyboard to disappear after pressing done
    daTextField.delegate = self;
}
person Community    schedule 13.11.2008
comment
Если вы добавили текстовое поле в раскадровку или NIB, вы также можете установить там delegate текстового поля. Вам не нужно делать это программно, как показано выше. Любой из подходов работает нормально. - person Rob; 18.01.2013

Вот трюк, позволяющий получить автоматическое отключение клавиатуры вообще без кода. В перо отредактируйте прокси-объект First Responder в Инспекторе удостоверений, добавив новое действие первого респондента; назовем это dummy:. Теперь подключите событие Did End on Exit текстового поля к действию dummy: прокси-объекта First Responder. Вот и все! Так как событие Did End on Exit текстового поля теперь имеет пару действие – цель, текстовое поле автоматически закрывает клавиатуру, когда пользователь нажимает Return; и поскольку нет наказания за то, что не найден обработчик для сообщения, отправленного вверх по цепочке респондента, приложение не аварийно завершает работу, даже если нигде нет реализации dummy:.

person matt    schedule 14.12.2010
comment
@matt Я обнаружил, что ЕСЛИ я добавлю переход отмотки и подключу событие didEndOnExit, ТО при нажатии Return будет запущен переход отмотки. Без подключения к событию переход не запускается. Отлично, но А? Замечания? Кстати: у меня есть ваши книги по Swift (готово) и iOS10 (глава 6). Они мне очень помогли! - person Verticon; 13.11.2017
comment
@Verticon вопрос и ответ не имеют ничего общего с переходами, поэтому я не понимаю, в чем проблема ... :( это чисто о увольнении клавиатуры - person matt; 13.11.2017
comment
@matt Извини, чувак. Я копил поддержку, потому что 1) я натолкнулся на эту тему, когда занимался обработкой ключа возврата UITextField; и 2) это была возможность пообщаться с вами (спасибо за книги). Нет никаких проблем. Просто непонимание с моей стороны того, почему и как это работает именно так. - person Verticon; 13.11.2017
comment
@Verticon Прошу прощения за то, что не смог помочь. Не стесняйтесь формулировать новый вопрос с дополнительной информацией (демонстрационный проект?) И сообщать мне, если я могу быть полезен. - person matt; 13.11.2017
comment
@matt Спасибо, stackoverflow.com/questions/47289747/ - person Verticon; 14.11.2017

Просто добавь

[textField endEditing:YES];

где вы хотите отключить клавиатуру и отобразить окно выбора.

person user415897    schedule 19.08.2010

В Swift вы можете написать IBAction в контроллере и установить событие Did End On Exit текстового поля для этого действия.

@IBAction func returnPressed(sender: UITextField) {
    self.view.endEditing(true)
}
person Safin Ahmed    schedule 08.05.2016

Swift 4.2 и он будет работать на 100%

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var textField: UITextField!


    override func viewDidLoad() {
        super.viewDidLoad()

        self.textField.delegate = self

    }

    // hide key board when the user touches outside keyboard

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
    }

    // user presses return key

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

}
person Gulsan Borbhuiya    schedule 09.07.2019
comment
Я оценил тот факт, что этот ответ также научил меня отключать клавиатуру, когда пользователь прикасается за ее пределами. - person Carl Smith; 28.12.2020

Вы также можете использовать

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
  {

   [self.yourTextField resignFirstResponder];

  }

Лучше всего, если у вас много Uitextfields:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
 {    
     [self.view endEditing:YES];
 }
person Metalhead1247    schedule 16.09.2014

Вот что мне нужно было сделать, чтобы заставить его работать, и я думаю, что это необходимо любому, у кого есть цифровая клавиатура для клавиатуры (или любые другие без кнопки «Готово»:

  1. Я изменил UIView в ViewController на UIControl.
  2. Я создал функцию под названием

    -(IBAction)backgroundIsTapped:(id)sender
    

Это также было определено в файле .h.

После этого я связался с битом «касания» для ViewController в Интерфейсном Разработчике.

В функции 'фоновое нажатие' я поставил следующее:

    [answerField resignFirstResponder];

Просто не забудьте изменить answerField на имя UITextField, из которого вы хотите удалить клавиатуру (очевидно, убедитесь, что ваш UITextField определен, как показано ниже :)

    IBOutlet UITextField * <nameoftextfieldhere>;

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

person Ryan Bourne    schedule 21.06.2012
comment
..но это не работает так хорошо, если пользователь нажимает другой элемент управления. - person ragnarius; 31.07.2014

Вы заметите, что метод textFieldShouldReturn предоставляет объект текстового поля, который нажал кнопку DONE. Если вы установите TAG, вы можете включить это текстовое поле. Или вы можете отслеживать и сравнивать указатель объекта с некоторым значением члена, сохраненным его создателем.

Мой подход к самообучению такой:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    NSLog(@"%s", __FUNCTION__);

    bool fDidResign = [textField resignFirstResponder];

    NSLog(@"%s: did %resign the keyboard", __FUNCTION__, fDidResign ? @"" : @"not ");

    return fDidResign;
}

Между тем, я поставил «проверочный» тест, который отрицает отставку. Это только для иллюстрации, поэтому, если пользователь вводит NO! в поле его не уволят. Поведение было таким, как я хотел, но последовательность вывода была не такой, как я ожидал.

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
    NSLog(@"%s", __FUNCTION__);

    if( [[textField text] isEqualToString:@"NO!"] ) {
        NSLog(@"%@", textField.text);
        return NO;
    } else {
        return YES;
    }
}

Ниже приводится мой вывод NSLog для этого отказа, за которым следует принятие. Вы заметите, что я возвращаю результат отставки, но я ожидал, что он вернет мне ЛОЖЬ, чтобы доложить вызывающему ?! В остальном у него необходимое поведение.

13.313 StudyKbd[109:207] -[StudyKbdViewController textFieldShouldReturn:]
13.320 StudyKbd[109:207] -[StudyKbdViewController textFieldShouldEndEditing:]
13.327 StudyKbd[109:207] NO!
13.333 StudyKbd[109:207] -[StudyKbdViewController textFieldShouldReturn:]: did resign the keyboard
59.891 StudyKbd[109:207] -[StudyKbdViewController textFieldShouldReturn:]
59.897 StudyKbd[109:207] -[StudyKbdViewController textFieldShouldEndEditing:]
59.917 StudyKbd[109:207] -[StudyKbdViewController doneEditText]: NO
59.928 StudyKbd[109:207] -[StudyKbdViewController textFieldShouldReturn:]: did resign the keyboard
person mobibob    schedule 01.10.2009
comment
Можете ли вы объяснить ... если я верну NO или YES, в обоих случаях произойдет то же самое, так что зачем возвращать yes в методе делегата textFieldShouldReturn - person K. Jaiswal; 06.04.2013

Вот довольно простой способ завершить редактирование с помощью клавиши возврата или касания в фоновом режиме.

В конструкторе интерфейсов вставьте свои поля в представление класса UIFormView.

Что делает этот класс:

  • Автоматически присоединяться как делегат полей (либо пробужденный из пера, либо добавленный вручную)
  • Сохранить ссылку на текущее редактируемое поле
  • Отключите клавиатуру при возврате или коснитесь в фоновом режиме

Вот код:

Интерфейс

#import <UIKit/UIKit.h>

@interface UIFormView : UIView<UITextFieldDelegate>

-(BOOL)textFieldValueIsValid:(UITextField*)textField;
-(void)endEdit;

@end

Реализация

#import "UIFormView.h"

@implementation UIFormView
{
    UITextField* currentEditingTextField;
}

// Automatically register fields

-(void)addSubview:(UIView *)view
{
    [super addSubview:view];
    if ([view isKindOfClass:[UITextField class]]) {
        if ( ![(UITextField*)view delegate] ) [(UITextField*)view setDelegate:self];
    }
}

// UITextField Protocol

-(void)textFieldDidBeginEditing:(UITextField *)textField
{
    currentEditingTextField = textField;
}

-(void)textFieldDidEndEditing:(UITextField *)textField
{
    currentEditingTextField = NULL;
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self endEdit];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    if ([self textFieldValueIsValid:textField]) {
        [self endEdit];
        return YES;
    } else {
        return NO;
    }
}

// Own functions

-(void)endEdit
{
    if (currentEditingTextField) {
        [currentEditingTextField endEditing:YES];
        currentEditingTextField = NULL;
    }
}


// Override this in your subclass to handle eventual values that may prevent validation.

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

@end
  • Создавая подклассы для формы и переопределив метод textFieldValueIsValid:, вы можете избежать завершения редактирования, если значение не является правильным для данного поля.

  • Если поле имеет делегат, установленный в Интерфейсном Разработчике, то форма не изменяет его. Я не вижу много причин для установки другого делегата для определенного поля, но почему бы и нет…

Есть много способов улучшить этот класс представления формы - прикрепить делегата, сделать некоторую компоновку, обработать, когда клавиатура покрывает поле (используя фрейм currentEditingTextField), автоматически запустить редакцию для следующего поля, ...

Я лично держу его в своей структуре и всегда делаю подклассы для добавления функций, он довольно часто бывает полезен «как есть».

Надеюсь, это поможет. Приветствую всех

person Moose    schedule 08.09.2015
comment
Полезный класс. Один небольшой момент: вы не должны добавлять в свои классы префиксы пользовательского интерфейса. В objective-c вы должны использовать свой собственный префикс (TL?), В Swift ничего не использовать. - person kubi; 10.09.2015
comment
Спасибо @kubi. Верно. В моем фреймворке это MF, вроде MooseFactory;) - person Moose; 11.09.2015

если вы хотите, чтобы все редактировалось в UIViewController, вы можете использовать.

[[self view]endEditing:YES];

и если вы хотите отклонить скрытую клавиатуру UITextField, используйте.

1. добавьте делегата в свой viewcontroller.h

<UITextFieldDelegate>
  1. сделать делегирование невозможным для вашего текстового поля.

    self.yourTextField.delegate = self;

  2. добавьте этот метод в свой viewcontroller.

    - (BOOL) textFieldShouldEndEditing: (UITextField *) textField {[textField resignFirstResponder]; вернуть ДА;}

person Abhimanyu Rathore    schedule 03.11.2015

Программно установить делегата UITextField в быстром 3

Реализуйте UITextFieldDelegate в файле ViewController.Swift (например, класс ViewController: UIViewController, UITextFieldDelegate {)

 lazy var firstNameTF: UITextField = {

    let firstname = UITextField()
    firstname.placeholder = "FirstName"
    firstname.frame = CGRect(x:38, y: 100, width: 244, height: 30)
    firstname.textAlignment = .center
    firstname.borderStyle = UITextBorderStyle.roundedRect
    firstname.keyboardType = UIKeyboardType.default
    firstname.delegate = self
    return firstname
}()

lazy var lastNameTF: UITextField = {

    let lastname = UITextField()
    lastname.placeholder = "LastName"
    lastname.frame = CGRect(x:38, y: 150, width: 244, height: 30)
    lastname.textAlignment = .center
    lastname.borderStyle = UITextBorderStyle.roundedRect
    lastname.keyboardType = UIKeyboardType.default
    lastname.delegate = self
    return lastname
}()

lazy var emailIdTF: UITextField = {

    let emailid = UITextField()
    emailid.placeholder = "EmailId"
    emailid.frame = CGRect(x:38, y: 200, width: 244, height: 30)
    emailid.textAlignment = .center
    emailid.borderStyle = UITextBorderStyle.roundedRect
    emailid.keyboardType = UIKeyboardType.default
    emailid.delegate = self
    return emailid
}()

// Отметка: - обработка делегата textField ..

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    view.endEditing(true)
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {

    if textField == firstNameTF {

        lastNameTF.becomeFirstResponder()
    }

    else if textField == lastNameTF {

        emailIdTF.becomeFirstResponder()
    }
    else {
        view.emailIdTF(true)
    }
    return true
}
person Tanjima Kothiya    schedule 28.12.2017

Создайте функцию hidekeyboard и свяжите ее с текстовым полем в файле .xib и выберите DidEndOnExit.

-(IBAction)Hidekeyboard    
{    
      textfield_name.resignFirstResponder;    
}  
person pooja_chaudhary    schedule 12.09.2013

Если вы создали представление с помощью Interface Builder, используйте следующее. Просто создайте метод,

-(IBAction)dismissKeyboard:(id)sender
{
[sender resignFirstResponder];
}

Просто щелкните правой кнопкой мыши текстовое поле в представлении, установите событие как «Завершилось при выходе» и подключите его к методу «dismissKeyboard».

Лучшее руководство для новичков - "Head First Разработка для iPhone и iPad, 2-е издание".

person chandru    schedule 13.11.2013

попробуй это

- (BOOL) textView: (UITextView*) textView shouldChangeTextInRange: (NSRange) range replacementText: (NSString*) text
{
    if ([text isEqualToString:@"\n"]) {
        [textView resignFirstResponder];
        return NO;
    }
    return YES;
}
person Vineesh TP    schedule 31.01.2014

Всем, кто ищет Swift 3

1) Убедитесь, что ваш делегат UITextField подключен к вашему ViewController в раскадровке.

2) Реализуйте UITextFieldDelegate в файле ViewController.Swift (например, класс ViewController: UIViewController, UITextFieldDelegate {)

3) Используйте метод делегата ниже

func textFieldShouldReturn(textField: UITextField) -> Bool { 
   textField.resignFirstResponder()  
return false }
person Burf2000    schedule 06.01.2017

Вот как я отключаю клавиатуру в Swift 4.2, и у меня она работает:

    override func viewDidLoad() {
    super.viewDidLoad()

    let tap = UITapGestureRecognizer(target: self, action: 
    #selector(dismissKeyboard))

    view.addGestureRecognizer(tap)
    }

    @objc func dismissKeyboard (_ sender: UITapGestureRecognizer) {
    numberField.resignFirstResponder()
    }
person Prakhar Prakash Bhardwaj    schedule 22.02.2019

Swift 3, iOS 9+

@IBAction private func noteFieldDidEndOnExit(_ sender: UITextField) {}

UPD: У меня все еще нормально работает. Я думаю, что парень, посвятивший этот ответ, просто не понял, что ему нужно привязать это действие к UITextField в раскадровке.

person Artem Deviatov    schedule 04.09.2017