How to Dismiss the Keyboard when using a UITextView

Oddly this was more tricky then I would have thought … perhaps for a veteran Cocoa developer this would have been obvious, but for the rest of us struggling to get rid of the keyboard on a UITextView here is the secret sauce …

The short answer is to send the UITextViewController the “resignFirstResponder” message … the trick however is when to send the message. In my case, and I assume it would be the same for others, is to listen for any changes to the text in the UITextView and if the carridge return character ‘\n’ is detected then send the “resignFirstResponder” message to the UITextView.

Step 1. The first step is to make sure that you declare support for the UITextViewDelegate protocol. This is done in your header file, as example here is the header called EditorController.h:

Step 2. Next you will need to register the controller as the UITextView’s delegate. Continuing from the example above, here is how I have initialize the UITextView with EditorController as the delegate …

Step 3. And now the final piece of the puzzle is to take action in response to the “shouldCahngeTextInRange” message as follows:

35 Comments

  1. since reading icodeblog.com I add this code the .m controller

    -(BOOL)textFieldShouldReturn:(UITextField *)theTextField {
    [txtName resignFirstResponder];
    return YES;
    }

  2. Thanks for the feedback. Unfortunately the delegate ‘textFieldShouldReturn:’ is not available for UITextView. You can only use it for UITextField. I wish it were … it would make UITextView easier to use!

  3. thanks for suggestion but it will work till we are not pressing return so only one line can be added at a time. It will not work while we want to add 5-6 line in text view. so what is the solution for multi line entry?

  4. Your point is correct. If you need to be able to add ‘\n’ characters then you will need to add a Cancel/Done button somewhere on your UI. I typically use the UIButtonBarItem class to create buttons for the left and right sides of the Nav Bar. I only add them when the text view becomes firstResponder.

  5. thanks for reply. can you provide me the sample code for the UIButtonBarItem class to create button for left and right of Nav Bar and to add them when text view become first responder.

  6. Hi, thanks for the tutorial. I am using the same method to see how many rows are in a textView. If the user presses return then the ‘\n’ is sent and it puts the textView on the next row however, if the text is wrapped it moves to the next line without sending a ‘\n’. You know of any way I can detect when that happens?

  7. Hi,

    I ve been searching all kinds of blog for this keypad dismissal (It comes as a welcome sign to see but to get rid of it…….. hmmm breaks ones neck). In my case i have 3 textfields and one of them i enter numbers. For the number keypad or the phone keypad there is no DONE button! How to get rid of it. For text entry the code given in iphone101 and (#Bug) does work but for this number case i am stuck. In one blog i read that i should add a button and assign it to the TextField “DidEndOnExit” event. I did that but once i try to see which is the first responder it does not work….. Here is the code

    //This works in a stupid fashion
    -(IBAction) getRidofResponder : (id) sender{
    [FirstTextField resignFirstResponder];
    [SecondTextField resignFirstResponder];
    [ThirdTextFieldPhoneNumber resignFirstResponder];
    }

    //This does not work
    -(IBAction) getRidofResponder : (id) sender{

    if([FirstTextField isFirstResponder])
    [FirstTextField resignFirstResponder];
    else if([SecondTextField isFirstResponder])
    [SecondTextField resignFirstResponder];
    else if([ThirdTextFieldPhoneNumber isFirstResponder])
    [ThirdTextFieldPhoneNumber resignFirstResponder]
    }

    Any help on this????? Is there another better way of solving this issue?
    Thanks

    • Set up notification for the key press and then just check to see if it is a \n and resign.

      In viewDidLoad

      [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(textViewKeyPressed:) name: UITextViewTextDidChangeNotification object: nil];

      and then

      -(void) textViewKeyPressed: (NSNotification*) notification {

      if ([[[notification object] text] hasSuffix:@”\n”])
      {
      [[notification object] resignFirstResponder];
      }

  8. @maxfiresolutions I am surprised that the second example didn’t work for you. I’ve not had a reason in my applications to test for isFirstResponder so I can’t say for sure that you are using it correctly.

    One thing you could do is register a delegate for the event that is generated when the UITextField becomes FirstResponder and associate the “active” TextView with some instance variable. That way when you need to resignFirstResponder you don’t need to test … just use the instance variable.

    Another place to look is at tapping into the NSNotificationCenter. I suspect there is an existing event you can register to receive in just such a case.

  9. ah this is great – worked for me, ‘cept I skipped the middle chunk of code (delegate part) and provided the connection in dreamweaver, I mean Interface Builder (referencing outlet of files owner delegate connected to the text view).

    Thank You for this excellent post!

    SF

  10. This never worked for me. I declared the hosting view controller to be the text view’s delegate, and added the method as shown. This method never gets called. Perhaps you assumed some other step that I am not aware of.

  11. Be sure to include the protocol after the UIViewController subclass interface header file.

  12. Be sure to include the UITextViewDelegate protocol after the UIViewController subclass interface header file.

  13. Anyone know of good method and/or spot that can be used to save the text if/when the UITextView’s keyboard is dismissed?

  14. To answer my own question…this worked:

    // Save the users comment
    – (void)textViewDidEndEditing:(UITextView *)textView{

    NSLog(@”textView.text: %@”, textView.text);

    }

    Just be sure you have implemented the UITextViewDelegate protocol in your .h file.

  15. Thanks very much for this trick. I’ve been searching and searching for how to get the keyboard to dismiss on the “Done” button. This seems like a bit of a hack, but at the same time, it allows for the most flexibility of behavior so I can see why it doesn’t automatically dismiss.

    Thanks again!

  16. This is how i did it and it works just fine,

    – First register for keyboradDidShow notification(in viewDidLoad):
    – have a button show up right above the end of the keyboard when the keyboard is shown(implemented in the notification)
    – add target to that button so that it discards the keyboard by sending the resignFirstResponder message to the text view.
    – also remove the button from the super view in the target method and it looks like the button is showing up with the keyboard. cheers.

    – (void)viewDidLoad
    {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector (keyboardDidShow:) name: UIKeyboardDidShowNotification object:nil];

    ….
    }

    -(void) keyboardDidShow: (NSNotification *)notif
    {
    NSLog(@”keyboard did show”);
    hideKeyboardButton = [UIButton buttonWithType: UIButtonTypeCustom];
    hideKeyboardButton.frame = CGRectMake(250, 173, 70, 30);
    [hideKeyboardButton setTitle:@”Cancel” forState: UIControlStateNormal];
    [hideKeyboardButton setBackgroundImage:[UIImage imageNamed:@”button.png”] forState: UIControlStateNormal];
    [hideKeyboardButton addTarget: self action:@selector(hideKeyboard) forControlEvents: UIControlEventTouchUpInside];
    [self.view addSubview: hideKeyboardButton];
    }

    -(void) hideKeyboard
    {
    [hideKeyboardButton removeFromSuperview];
    [yourTextView resignFirstResponder];
    }

    • This worked for me as the UITextView was being used so someone could add notes, (attribute for an entity in core data). I could not assume they would let the text wrap but they might wish to use a newline. Therefore the return key had to function as default. cheers

  17. Great work Man. U deserve kudos . Hoping 2 see some more code from your side. Thanks a lot !!!!

  18. This works very well for me and requires view little coding

    – (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@”User touched”);
    UITouch *touch = [touches anyObject];

    if ([textView isFirstResponder] && [touch view] != textView) {
    NSLog(@”The textView is currently being edited, and the user touched outside the text view”);
    [textView resignFirstResponder];
    }
    }

    • How do you make it so when you tap done it will also retract the keyboard

    • thank you thank you thank you thank you thank you thank you thank you thank you

  19. This is a very nice article for iphone application developers and It saved my time of development.

    Thanks to write a nice article and post it on your blog publicly.

  20. Great!! Thanks a lot, solved my problem in 5 minutes….

  21. Really appreciate this and Thanks also go to those commenting, some very useful stuff there!

  22. Thanks a lot,

    here i found everything that i expected. Solve my probleme in only 10 minutes.

    Keep writing article like that, very helpfull.

    BB

  23. I was actually stuck with this problem today…..got the solution….thanks alot

Comments are closed.