How do you dismiss the keyboard when editing a UITextField
Asked Answered
R

22

192

I know that I need to tell my UITextField to resign first responder when I want to dismis the keyboard, but I'm not sure how to know when the user has pressed the "Done" key on the keyboard. Is there a notification I can watch for?

Roughcast answered 8/11, 2008 at 3:47 Comment(1)
[self.view endEditing:YES]; in touches began delegate is the best solutionColucci
R
358

I set the delegate of the UITextField to my ViewController class.

In that class I implemented this method as following:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    [textField resignFirstResponder];
    return NO;
}
Roughcast answered 8/11, 2008 at 4:16 Comment(7)
See the example above... wire that using IntefaceBuilder to the action on whatever you're using as your controller... whenever the user dismisses the text entry system (presses done), this will be invoked...Bucket
Either of these will work - the text field sends its action when the user hits the Return ("Done", whatever) key, and also sends its delegate -textFieldShouldReturn:.Eidolon
BTW - this also works for a UISearchBar. For example, my code I had a member IBOutlet searchBarTusb; When my 'return key' (UIReturnKeySearch) was clicked, -(void) searchBarSearchButtonClicked:, I put the statement [searchBarTusb resignFirstResponder]; Also note, the 'return key' was set in the NIB using Interface Builder.Oriole
Why return NO instead of YES?Chanachance
@IulianOnofrei The default behavior of the return button is to add a line return and keep the keyboard onscreen. By returning NO you avoid adding a line return to the text.Roughcast
I am returning YES and it doesn't add a line to the text.Chanachance
This no longer works. You have to dismiss the keyboard after a delay. func textFieldShouldClear(_ textField: UITextField) -> Bool { DispatchQueue.main.async { self.resignFirstResponder() } return true } Bina
B
48

If you connect the DidEndOnExit event of the text field to an action (IBAction) in InterfaceBuilder, it will be messaged when the user dismisses the keyboard (with the return key) and the sender will be a reference to the UITextField that fired the event.

For example:

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

Then, in InterfaceBuilder, link the DidEndOnExit event of the text field to this action on your controller (or whatever you're using to link events from the UI). Whenever the user enters text and dismisses the text field, the controller will be sent this message.

Bucket answered 8/11, 2008 at 3:51 Comment(5)
The only event that seems like it might work is textFieldDidEndEditing, which states it's only sent after the UITextField resigns first responder status. How do I know when I need to resign first responder status?Roughcast
I'm sorry about the terminology... it's not an actual notification (event)... I'm going to edit my answer with a quick example and explanation, so see that :)Bucket
To clarify this answer, the textField sends the "Did End On Exit" event when you hit the return key, so that's the one you need to link to your controller. I think this method is easier than the one I outlined above.Roughcast
could you edit this answer so that it mentions WHICH event to wire, please? This is obviously nicer than setting the delegate.Targum
Want to upvote this answer, but can't until it mentions the DidEndOnExit event. Someone with edit privileges please make the change if the OP won't?Absher
A
33

You can also create a method in your controller

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

and then in Connection Inspector in IB connect Event "Did End On Exit" to it.

Acclimate answered 1/5, 2009 at 20:20 Comment(1)
This is almost incorrect, or at least it misses the point. By subscribing to the DidEndOnExit event, you do not need to call resignFirstResponder. You can test this by putting a symbolic breakpoint on [UIResponder resignFirstResponder]. Note that even if if you don't call resignFirstResponder, it still gets called by the system. This is explained in Matt Neuburg's excellent book(s): apeth.com/iOSBook/…Aggregation
G
20

kubi, thanks. Your code worked. Just to be explicit (for newbies like) as you say you have to set the UITextField's delegate to be equal to the ViewController in which the text field resides. You can do this wherever you please. I chose the viewDidLoad method.

- (void)viewDidLoad 
{
    // sets the textField delegates to equal this viewController ... this allows for the keyboard to disappear after pressing done
    daTextField.delegate = self;
}
Genna answered 13/11, 2008 at 2:44 Comment(1)
If you added text field to your storyboard or NIB, you can set the text field's delegate there, too. You don't have to do this programmatically, as demonstrated above. Either approach works fine.Femur
S
19

Here is a trick for getting automatic keyboard dismissal behavior with no code at all. In the nib, edit the First Responder proxy object in the Identity inspector, adding a new first responder action; let's call it dummy:. Now hook the Did End on Exit event of the text field to the dummy: action of the First Responder proxy object. That's it! Since the text field's Did End on Exit event now has an action–target pair, the text field automatically dismisses its keyboard when the user taps Return; and since there is no penalty for not finding a handler for a message sent up the responder chain, the app doesn't crash even though there is no implementation of dummy: anywhere.

Selma answered 14/12, 2010 at 22:51 Comment(5)
@Selma I discovered that IF I add an unwind segue AND connect the didEndOnExit event THEN the unwind segue will be triggered upon pressing Return. Without the event connection the segue is not triggered. Great but Huh? Any remarks? BTW: I have your Swift (finished) and iOS10 (on chap 6) books. They have helped me tremendously!Insufficiency
@Insufficiency the question and answer has nothing to do with segues, so I don't understand the issue... :( this is purely about keyboard dismissalSelma
@Selma Sorry, man. I was piggy backing because 1) I came upon this thread while I was dealing with how to handle the UITextField's return key; and 2) it was a chance to interact with you (thx for da books). There is no "issue". Just a lack of understanding on my part about why/how it works the way it does.Insufficiency
@Insufficiency I apologize for not being able to help. Feel free to formulate a new question with more info (demo project?) and blip me, if I can be useful.Selma
@Selma Thanks #47290247Insufficiency
C
12

In Swift you can write an IBAction in the Controller and set the Did End On Exit event of the text field to that action

@IBAction func returnPressed(sender: UITextField) {
    self.view.endEditing(true)
}
Carpo answered 8/5, 2016 at 23:22 Comment(0)
L
12

Swift 4.2 and It will work 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
    }

}
Lesslie answered 9/7, 2019 at 3:26 Comment(1)
I appreciated the fact that this answer also taught me how to dismiss the keyboard when the user touches outside it.An
O
11

Just add

[textField endEditing:YES];

where you want to disable keyboard and display the picker view.

Oswell answered 19/8, 2010 at 0:50 Comment(1)
But the question is asking how to know when the user taps the Done button on the keyboard. This answer doesn't address that at all.Confutation
C
4

You can also use

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

   [self.yourTextField resignFirstResponder];

  }

Best one if You have many Uitextfields :

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
 {    
     [self.view endEditing:YES];
 }
Cobby answered 16/9, 2014 at 7:36 Comment(0)
O
2

You will notice that the method "textFieldShouldReturn" provides the text-field object that has hit the DONE key. If you set the TAG you can switch on that text field. Or you can track and compare the object's pointer with some member value stored by its creator.

My approach is like this for a self-study:

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

    bool fDidResign = [textField resignFirstResponder];

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

    return fDidResign;
}

Meanwhile, I put the "validation" test that denies the resignation follows. It is only for illustration, so if the user types NO! into the field, it will not dismiss. The behavior was as I wanted, but the sequence of output was not as I expected.

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

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

Following is my NSLog output for this denial followed by the acceptance. You will notice that I am returning the result of the resign, but I expected it to return FALSE to me to report back to the caller?! Other than that, it has the necessary behavior.

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
Oriole answered 1/10, 2009 at 2:18 Comment(1)
can u explain ..if i return NO or YES in both case same things happen so what the need of returning yes in textFieldShouldReturn delegate methodManipulate
T
2

Here's what I had to do to get it to work, and I think is necessary for anyone with a Number Pad for a keyboard (or any other ones without a done button:

  1. I changed the UIView in the ViewController to a UIControl.
  2. I created a function called

    -(IBAction)backgroundIsTapped:(id)sender
    

This was also defined in the .h file.

After this, I linked to to the 'touch down' bit for the ViewController in Interface Builder.

In the 'background is tapped' function, I put this:

    [answerField resignFirstResponder];

Just remember to change 'answerField' to the name of the UITextField you want to remove the keyboard from (obviously make sure your UITextField is defined like below:)

    IBOutlet UITextField * <nameoftextfieldhere>;

I know this topic probably died a long time ago... but I'm hoping this will help someone, somewhere!

Trio answered 21/6, 2012 at 16:52 Comment(1)
..but it does not work so well if the user taps another control.Granthem
W
1

Here is a quite clean way to end edition with the Return Key or a touch in the background.

In Interface builder, embed your fields in a view of class UIFormView

What does this class :

  • Automatically attach itself as fields delegate ( Either awaked from nib, or added manually )
  • Keep a reference on the current edited field
  • Dismiss the keyboard on return or touch in the background

Here is the code :

Interface

#import <UIKit/UIKit.h>

@interface UIFormView : UIView<UITextFieldDelegate>

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

@end

Implementation

#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
  • By subclassing the form and overriding the textFieldValueIsValid: method, you can avoid end of edition if the value is not correct for the given field.

  • If a field has a delegate set in Interface Builder, then the form does not change it. I don't see many reasons to set a different delegate to a particular field, but why not…

There is many ways to improve this form view class - Attach a delegate, do some layout, handle when the keyboards covers a field ( using the currentEditingTextField frame ), automatically start edition for the next field, ...

I personally keep it in my framework, and always subclass it to add features, it is quite often useful "as-is".

I hope it will helps. Cheers all

Willful answered 8/9, 2015 at 0:54 Comment(2)
Helpful class. One small point, you shouldn't prefix your own classes with "UI". In objective-c you should use your own prefix ("TL"?), in Swift, don't use anything.Roughcast
Thanks @kubi. That's right. It is MF in my framework, like MooseFactory ;)Willful
S
1

if you want all editing of in a UIViewController you can use.

[[self view]endEditing:YES];

and if you want dismiss a perticular UITextField keyboard hide then use.

1.add delegate in your viewcontroller.h

<UITextFieldDelegate>
  1. make delegation unable to your textfield .

    self.yourTextField.delegate = self;

  2. add this method in to your viewcontroller.

    -(BOOL)textFieldShouldEndEditing:(UITextField *)textField{ [textField resignFirstResponder]; return YES;}

Sachi answered 3/11, 2015 at 10:25 Comment(0)
E
1

Anyone looking for Swift 3

1) Make sure your UITextField's Delegate is wired to your ViewController in the Storyboard

2) Implement UITextFieldDelegate in your ViewController.Swift file (e.g class ViewController: UIViewController, UITextFieldDelegate { )

3) Use the delegate method below

func textFieldShouldReturn(textField: UITextField) -> Bool { 
   textField.resignFirstResponder()  
return false }
Entablement answered 6/1, 2017 at 15:53 Comment(0)
J
1

Programmatically set the delegate of the UITextField in swift 3

Implement UITextFieldDelegate in your ViewController.Swift file (e.g class 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
}()

// Mark:- handling delegate 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
}
Jugate answered 28/12, 2017 at 5:27 Comment(0)
C
0

Create a function hidekeyboard and link it to the textfield in the .xib file and select DidEndOnExit

-(IBAction)Hidekeyboard    
{    
      textfield_name.resignFirstResponder;    
}  
Critic answered 12/9, 2013 at 10:12 Comment(0)
H
0

If you have created the view using Interface Builder, Use the following Just create a method,

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

Just right click the text field in the view , and set the event as Did End on Exit, and wire it to the method "dismissKeyboard".

The best guide for beginners is "Head First iPhone and iPad Development, 2nd Edition"

Harass answered 13/11, 2013 at 9:50 Comment(0)
S
0

try this

- (BOOL) textView: (UITextView*) textView shouldChangeTextInRange: (NSRange) range replacementText: (NSString*) text
{
    if ([text isEqualToString:@"\n"]) {
        [textView resignFirstResponder];
        return NO;
    }
    return YES;
}
Schexnayder answered 31/1, 2014 at 13:52 Comment(0)
B
0
//====================================================
//                  textFieldShouldReturn:
//====================================================
-(BOOL) textFieldShouldReturn:(UITextField*) textField { 
    [textField resignFirstResponder];
    if(textField.returnKeyType != UIReturnKeyDone){
        [[textField.superview viewWithTag: self.nextTextField] becomeFirstResponder];
    }
    return YES;
}
Bik answered 14/9, 2014 at 2:52 Comment(0)
I
0

This is how I dismiss the keyboard in Swift 4.2 and it works for me:

    override func viewDidLoad() {
    super.viewDidLoad()

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

    view.addGestureRecognizer(tap)
    }

    @objc func dismissKeyboard (_ sender: UITapGestureRecognizer) {
    numberField.resignFirstResponder()
    }
Irons answered 22/2, 2019 at 8:52 Comment(0)
S
0

With Xcode 14.3.1, you don't need to add UITextFieldDelegate to the class. Drag from the TextField to the ViewController with Primary Action Triggered selected as control event as shown in the screenshot, sender.resignFirstResponder() should work.

Primary Action Triggered event

Soho answered 12/10, 2023 at 1:45 Comment(0)
S
-6
textField.returnKeyType = UIReturnKeyDone;
Silicone answered 24/6, 2013 at 17:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.