492

I'm wondering how to make the keyboard disappear when the user touches outside of a UITextField.

Tamás Sengel
  • 55,884
  • 29
  • 169
  • 223
jonepatr
  • 7,769
  • 7
  • 30
  • 53
  • 8
    Dmitry had the correct answer. This is not a gesture problem - its a problem of resigning the first responder. Dmirty's answer is also the solution recommended by Mark, Nutting and LeMarche in [Beginning iOS 4 Development](http://www.amazon.com/dp/143023024X), Chapter 4, page 83. – jww Jan 08 '13 at 23:39

38 Answers38

791

You'll need to add an UITapGestureRecogniser and assign it to the view, and then call resign first responder on the UITextField on it's selector.

The code:

In viewDidLoad

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];

[self.view addGestureRecognizer:tap];

In dismissKeyboard:

-(void)dismissKeyboard 
{
    [aTextField resignFirstResponder];
}

(Where aTextField is the textfield that is responsible for the keyboard)

Swift 3 version looks like that

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard (_:)))
self.view.addGestureRecognizer(tapGesture)

For dismissKeyboard

@objc func dismissKeyboard (_ sender: UITapGestureRecognizer) {
    aTextField.resignFirstResponder()
}
Vadim F.
  • 881
  • 9
  • 21
Jensen2k
  • 8,388
  • 1
  • 14
  • 13
  • 7
    This works but what it does is it also disables or makes navigation bar buttons as unclickable. So is there a work around for this? – Parth Bhatt Mar 15 '11 at 09:20
  • 4
    This doesn't work when the user do other gesture like scrolling. A better solution is to use hitTest:withEvent: – Enzo Tran Jan 05 '12 at 16:09
  • 4
    This is not good if you need to touch the "X" icon on the right of the textfield to clean the field. If you enable the gesture recognizer, you need to keep it enable while the focus is on the textField and therefore you can't touch such "X" icon. – aneuryzm Aug 15 '12 at 13:59
  • 1
    Try this instead: http://stackoverflow.com/questions/1456120/hiding-the-keyboard-when-losing-focus-on-a-uitextview – aneuryzm Aug 15 '12 at 14:13
  • this is worked for me but i have one button with checkbox functionality but its not working as a checkbox after applying this – Karthik Apr 13 '13 at 04:56
  • 2
    Need to be added: `- (void)textFieldDidBeginEditing:(UITextField *)textField { textFieldToResign = textField; }` this will help to resign selected textField – Nazir Apr 21 '13 at 09:52
  • 145
    I think better than `[aTextField resignFirstResponder]` would be `[self.view endEditing:YES];` it do not need a reference to the text field and will work for multiple textfields – Julian May 07 '14 at 09:29
  • 90
    So without having to define any methods, a one-liner would be: `[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self.view action:@selector(endEditing:)]];` – Subhas Aug 11 '14 at 07:11
  • 12
    @ParthBhatt I added `[tap setCancelsTouchesInView:NO];` per @qiaoyi 's answer; I had an issue with a table not responding to row selections. 5 years later, I hope this helps someone else. – Tom Howard Jun 06 '16 at 18:44
  • 12
    Swift one-liner: `self.view.addGestureRecognizer(UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:))))` – Malfunction Oct 24 '17 at 12:58
  • Be aware this will also prevent selection of rows in a static tableview – Duncan Groenewald May 17 '18 at 22:53
  • FYI: about `endEditing` – If the force parameter is set to true, the text field is never even asked to resign. So better to: `view.endEditing(false)` – dimpiax May 29 '18 at 21:22
  • Swift `addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(endEditing(_:))))` – dimpiax Aug 22 '18 at 00:07
  • How about if there is a UIButton, I want to hide the keyboard, and the UIButton touch action also works when the user touching the button? The solution doesn't work in that scenario. – DàChún May 27 '20 at 19:04
  • This solution not work along view inside subview.... need UITapGestureRecognizer object to add "cancelsTouchesInView " = false look my better solution look my answer https://stackoverflow.com/questions/5306240/ios-dismiss-keyboard-when-touching-outside-of-uitextfield/64335128#64335128 – Ucdemir Oct 13 '20 at 17:25
181

I mashed up a few answers.

Use an ivar that gets initialized during viewDidLoad:

UIGestureRecognizer *tapper;

- (void)viewDidLoad
{
    [super viewDidLoad];
    tapper = [[UITapGestureRecognizer alloc]
                initWithTarget:self action:@selector(handleSingleTap:)];
    tapper.cancelsTouchesInView = NO;
    [self.view addGestureRecognizer:tapper];
}

Dismiss what ever is currently editing:

- (void)handleSingleTap:(UITapGestureRecognizer *) sender
{
    [self.view endEditing:YES];
}
drewish
  • 9,042
  • 9
  • 38
  • 51
  • Fantastic, it works on UITableView!! it save my day! As a side note I will use [UITextField resignFirstResponder] instead of [UIView endEditing:] because I have more UITextField and endEditing gives a wrong scrolling position even if the new UITextField is visible. – Dr.Luiji Nov 08 '12 at 10:42
  • 1
    Dead wrong because the UITapGestureRecognizer is never added to to the view! –  Jun 11 '13 at 11:01
  • 1
    What is the purpose of cancelsTouchesInView here? – Adam Johns Jan 15 '15 at 21:15
  • 4
    If you don't add cancelsTouchesInView = false here, then you won't be able to select other types of items in your view. Your taps will be intercepted by the gestureRecognizer. – HalR Nov 16 '16 at 23:59
106

Check this, this would be the easiest way to do that,

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
      [self.view endEditing:YES];// this will do the trick
}

Or

This library will handle including scrollbar auto scrolling, tap space to hide the keyboard, etc...

https://github.com/michaeltyson/TPKeyboardAvoiding

Prasad De Zoysa
  • 2,488
  • 2
  • 23
  • 30
  • @Ramesh yes it does, but not in this way. you need to create a subclass from UITableView and inside that class implement the touchesBegan method and then call endEditing method. it works! don't forget to set the class for your table in the nib with newly created class. – Prasad De Zoysa Jan 14 '13 at 19:18
  • 3
    It doesn't hide keyboard when user touches on other controls on view. Ex: I have a UIButton and UITextField on UIView. I tap on UITextField, then tap on the button, the keyboard does not hide in this case. – Jacob Dam May 25 '13 at 11:16
  • 2
    @JacobDam You're right. The goal is to resignfirstresponder to hide the keyboard if *anything* happens outside of aTextField. –  Jun 11 '13 at 10:44
90

I see that some people are having issues using the UITapGestureRecognizer method. The easiest way that I've accomplished this functionality while still leaving my existing button's tap behavior intact is adding only one line to @Jensen2k 's answer:

[tap setCancelsTouchesInView:NO];

This allowed my existing buttons to still work without using @Dmitry Sitnikov 's method.

Read about that property here (search for CancelsTouchesInView): UIGestureRecognizer Class Reference

I'm not sure how it would work with scrollbars, as I see some had issues with, but hopefully someone else might run into the same scenario I had.

Rishil Patel
  • 1,977
  • 3
  • 14
  • 30
Joey
  • 1,075
  • 8
  • 8
  • 3
    I would also like to add, for those having a background image at the back of the view using `UIImageView`, add `[imageView setUserInteractionEnabled:NO];` and you "click through" it, which make this method work. – Paul Peelen Sep 23 '12 at 21:05
56

It is better to make your UIView an instance of UIControl (in interface builder) and then connect their TouchUpInside event to dismissKeyboard method. This IBAction method will look like:

- (IBAction)dismissKeyboard:(id)sender {
    [aTextBox resignFirstResponder];
}
Rishil Patel
  • 1,977
  • 3
  • 14
  • 30
fo2rist
  • 1,903
  • 15
  • 22
  • 1
    Thanks! This worked for me and other solutions did not. (`UITapGestureRecognizer` interfered with tapping on buttons inside the view). `touchesEnded` did not work because there was a `UIScrollView` messing with the responder chain.) – jlstrecker Dec 06 '11 at 20:34
  • If there are buttons inside the view and tapping them should dismiss the keyboard, you also have to connect their Touch Down event to `-dismissKeyboard`. – jlstrecker Dec 14 '11 at 05:06
  • 1
    This works great, but has to be added to anything you want to have dismiss the keyboard. Is there a way to automatically have a text box resign first responder on tapping anything else? – Isaac Overacker Feb 10 '12 at 05:55
  • @IsaacOveracker: see my answer below. – Enzo Tran Mar 25 '12 at 19:16
  • 4
    You shouldn't need to make UIView a UIControl. Make sure the UIView has User Interaction Enabled. – Sofi Software LLC Jul 17 '12 at 04:01
  • This method is recommended by Jeff LeMarch in [Beginning iOS 4 Development](http://www.amazon.com/dp/143023024X) (et al). Chapter 4, page 83. – jww Jan 08 '13 at 23:37
  • 1
    @SofiSoftwareLLC Your suggestion didn't work for me. I had to make it a UIControl even when User Interaction Enabled was checked. – three-cups Oct 18 '13 at 19:46
  • 1
    Using a StoryBoard I changed UIView to UIControl (where I would have selected a UIView subclass had I made one). It works well. I haven't run into any issues. iOS8. – ToddB Apr 28 '15 at 17:10
49

Swift 4

Setup your UIViewController with this extension method once e.g in viewDidLoad:

override func viewDidLoad() {
    super.viewDidLoad()
    self.setupHideKeyboardOnTap()
}

and the keyboard will be dismissed even by tapping on the NavigationBar.

import UIKit
extension UIViewController {
    /// Call this once to dismiss open keyboards by tapping anywhere in the view controller
    func setupHideKeyboardOnTap() {
        self.view.addGestureRecognizer(self.endEditingRecognizer())
        self.navigationController?.navigationBar.addGestureRecognizer(self.endEditingRecognizer())
    }

    /// Dismisses the keyboard from self.view
    private func endEditingRecognizer() -> UIGestureRecognizer {
        let tap = UITapGestureRecognizer(target: self.view, action: #selector(self.view.endEditing(_:)))
        tap.cancelsTouchesInView = false
        return tap
    }
}
FBente
  • 2,160
  • 23
  • 34
28

Swift version, this works in combination with other elements (like a UIButton or another UITextField):

override func viewDidLoad() {
    super.viewDidLoad()

    let tapper = UITapGestureRecognizer(target: self, action:#selector(endEditing))
    tapper.cancelsTouchesInView = false
    view.addGestureRecognizer(tapper)
}
Rob
  • 4,927
  • 12
  • 49
  • 54
17

This is a good generic solution:

Objective-C:

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

Swift:

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    self.view.endEditing(true)
}

Based on @icodebuster solution: https://stackoverflow.com/a/18756253/417652

Community
  • 1
  • 1
eduludi
  • 1,618
  • 21
  • 23
17

How about this: I know this is an old post. It might help someone :)

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {  
    NSArray *subviews = [self.view subviews];
    for (id objects in subviews) {
        if ([objects isKindOfClass:[UITextField class]]) {
            UITextField *theTextField = objects;
            if ([objects isFirstResponder]) {
                [theTextField resignFirstResponder];
            }
        } 
    }
}
Alex Zavatone
  • 4,106
  • 36
  • 54
Mr H
  • 5,254
  • 3
  • 38
  • 43
15

Swift 4 oneliner

view.addGestureRecognizer(UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:))))
newDeveloper
  • 1,365
  • 1
  • 17
  • 27
10

I think the easiest (and best) way to do this is to subclass your global view and use hitTest:withEvent method to listen to any touch. Touches on keyboard aren't registered, so hitTest:withEvent is only called when you touch/scroll/swipe/pinch... somewhere else, then call [self endEditing:YES].

This is better than using touchesBegan because touchesBegan are not called if you click on a button on top of the view. It is better than UITapGestureRecognizer which can't recognize a scrolling gesture for example. It is also better than using a dim screen because in a complexe and dynamic user interface, you can't put dim screen everywhere. Moreover, it doesn't block other actions, you don't need to tap twice to select a button outside (like in the case of a UIPopover).

Also, it's better than calling [textField resignFirstResponder], because you may have many text fields on screen, so this works for all of them.

MAhipal Singh
  • 4,745
  • 1
  • 42
  • 57
Enzo Tran
  • 5,750
  • 6
  • 31
  • 36
  • Unfortunately, this seems to interfere with UISearchBar's 'X' to clear text. – huggie Dec 03 '12 at 08:43
  • 1
    there are some problems with this approach. for example, you cant scroll a scrollview without loosing focus on your textfield. not advisable for more complex scenarios... personally, i prefer the uicontrol-version from Dmitry, maybe extended by the coment from Sofi Software. – katzenhut Jun 29 '13 at 14:49
  • One example of the scrolling is in the email app, when you are typing into the search bar and then scroll the mail list, the keyboard is dismissed. – Enzo Tran Jul 05 '13 at 13:30
  • Its the best approach and had done to my other projects. – Chandramani May 04 '18 at 15:38
9

This must be the easiest way to hide your keyboard by touching outside :

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

(from How to dismiss keyboard when user tap other area outside textfield?)

Community
  • 1
  • 1
7

If the view is embedded at all in a UIScrollView then you can use the following:

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

The former will animate the keyboard off screen when the table view is scrolled and the later will hide the keyboard like the stock Messages app.

Note that these are are available on iOS 7.0 or above.

Joe Masilotti
  • 16,815
  • 6
  • 77
  • 87
6

You can do this using the Storyboard in XCode 6 and above:


Create the action to hide the keyboard

Add this to the header file of the class used by your ViewController:

@interface TimeDelayViewController : UIViewController <UITextFieldDelegate>

- (IBAction)dissmissKeyboardOnTap:(id)sender;

@end

Then add this to the implementation file of the same ViewController:

- (IBAction)dissmissKeyboardOnTap:(id)sender{
    [[self view]endEditing:YES];
}

This will now be one of the 'Received Actions' for your storyboard scene (i.e. ViewController):

enter image description here


Hook up the action to the user event

Now you need to hook up this action to the user gesture of touching off the keyboard.

Important - You need to convert the 'UIView' that's contained in your storyboard to a UIControl, so it can receive events. Select the view from your View Controller Scene hierarchy:

enter image description here

...and change its class:

enter image description here

Now drag from the small circle next to the 'received action' for your scene, onto an 'empty' part of your scene (actually you're dragging the 'Received Action' to the UIControl). You'll be shown a selection of events that you can hook up your action to:

enter image description here

Select the 'touch up inside' option. You've now hooked the IBAction you created to a user action of touching off the keyboard. When the user taps off the keyboard, it will now be hidden.

(NOTE: To hook the action to the event, you can also drag from the received action directly onto the UIControl in your View Controllers hierarchy. It's displayed as 'Control' in the hierarchy.)

Chris Halcrow
  • 28,994
  • 18
  • 176
  • 206
5

If I got you right you want to resign keyboard wile tapping on outSide of textfield but you don't have reference of your textfield.

Try this;

  • Take global textField, lets call it reftextField
  • Now in textFieldDidBeginEditing set referenced text field to

    - (void) textFieldDidBeginEditing:(UITextField *)textField{
        reftextField = textField;
    }
    
  • Now you can happily use on any button clock, (adding a transparent button on begin editing recomended)

    - (void)dismissKeyboard {
          [reftextField resignFirstResponder];
    }
    
  • Or for resigning done button try this.

    //for resigning on done button    
    - (BOOL) textFieldShouldReturn:(UITextField *)textField{
        [textField resignFirstResponder];
        return YES;
    }
    
rptwsthi
  • 10,094
  • 10
  • 68
  • 109
5

In swift 5 You can use following code to dismiss keyboard outside textfield

override func viewDidLoad() {
    // ... code

    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard(_:)))
    self.view.addGestureRecognizer(tapGesture)  
}

@objc func dismissKeyboard(_ sender: UITapGestureRecognizer) {
    self.view.endEditing(true)
}
cro
  • 2,437
  • 2
  • 10
  • 9
Mohammad Muddasir
  • 947
  • 10
  • 21
  • 1
    If your view also has `tableViews` or `collectionViews` in it, include the following as part of the tapGesture configuration: `tapGesture.cancelsTouchesInView = false` – cro Apr 27 '20 at 09:40
4

Just to add to the list here my version of how to dismiss a keyboard on outside touch.

viewDidLoad:

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
[self.view addGestureRecognizer:singleTap];

Anywhere:

-(void)handleSingleTap:(UITapGestureRecognizer *)sender{
    [textFieldName resignFirstResponder];
    puts("Dismissed the keyboard");
}
John Riselvato
  • 12,854
  • 5
  • 62
  • 89
4

Objective-C:

Add this code in your ViewController.m file :

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

Swift:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    view.endEditing(true)
}
aashish tamsya
  • 4,903
  • 3
  • 23
  • 34
  • 1
    Sweeet! I love this one answer. Precise and as small as possible. Why bother setting up gesture recognizers and all other boilerplate? this should be the accepted answer – Adrian Salazar May 03 '21 at 15:37
3

Plenty of great answers here about using UITapGestureRecognizer--all of which break UITextField's clear (X) button. The solution is to suppress the gesture recognizer via its delegate:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    BOOL touchViewIsButton = [touch.view isKindOfClass:[UIButton class]];
    BOOL touchSuperviewIsTextField = [[touch.view superview] isKindOfClass:[UITextField class]];
    return !(touchViewIsButton && touchSuperviewIsTextField);
}

It's not the most robust solution but it works for me.

skedastik
  • 654
  • 7
  • 14
  • Exactly, All above things fails if i tap in the same textfield. It resigns even the textfield is my responder. and it also closes keyboard on tapping clear button inside the textField – Mrug May 09 '14 at 09:58
  • I would simplify it by just doing the test for button: `return !touchViewIsButton`. I guess any other buttons that need to dismiss the keyboard should do it in their actions. In addition TouchUpInside might not get called when the layout changes on keyboard dismissal. – Marián Černý Jun 13 '16 at 05:11
3

You can create category for the UiView and override the touchesBegan meathod as follows.

It is working fine for me.And it is centralize solution for this problem.

#import "UIView+Keyboard.h"
@implementation UIView(Keyboard)

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.window endEditing:true];
    [super touchesBegan:touches withEvent:event];
}
@end
Hiren
  • 689
  • 6
  • 12
3

Swift version of @Jensen2k's answer:

let gestureRecognizer : UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: "dismissKeyboard")
self.view.addGestureRecognizer(gestureRecognizer)

func dismissKeyboard() {
    aTextField.resignFirstResponder()
}

One liner

self.view.addTapGesture(UITapGestureRecognizer.init(target: self, action: "endEditing:"))
krema
  • 939
  • 7
  • 20
Syed Asad Ali
  • 1,308
  • 1
  • 9
  • 14
2

I tried many of the responses here and had no luck. My tap gesture recognizer was always causing my UIButtons to not respond when tapped, even when I set the cancelsTouchesInView property of the gesture recognizer to NO.

This is what eventually solved the issue:

Have an ivar:

UITapGestureRecognizer *_keyboardDismissGestureRecognizer;

When a text field begins editing, set the gesture recognizer:

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    if(_keyboardDismissGestureRecognizer == nil)
    {
        _keyboardDismissGestureRecognizer = [[[UITapGestureRecognizer alloc]
                                       initWithTarget:self
                                       action:@selector(dismissKeyboard)] autorelease];
        _keyboardDismissGestureRecognizer.cancelsTouchesInView = NO;

        [self.view addGestureRecognizer:_keyboardDismissGestureRecognizer];
    }
}

Then the trick is in how you set up the dismissKeyboard method:

- (void) dismissKeyboard
{
    [self performSelector:@selector(dismissKeyboardSelector) withObject:nil afterDelay:0.01];
}

- (void) dismissKeyboardSelector
{
    [self.view endEditing:YES];

    [self.view removeGestureRecognizer:_keyboardDismissGestureRecognizer];
    _keyboardDismissGestureRecognizer = nil;
}

I guess there's just something about getting the dismissKeyboardSelector execution out of the touch handling execution stack...

Rishil Patel
  • 1,977
  • 3
  • 14
  • 30
jeremywhuff
  • 2,911
  • 3
  • 29
  • 33
2

I used Barry example for my new development. It worked great! but i had to include a slightly change, required to dismiss the keyboard only for the textfield being edited.

So, I added to Barry example the following:

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    _textBeingEdited = textField;
}
-(void) textFieldDidEndEditing:(UITextField *)textField
{
    _textBeingEdited = nil;
}

Also, I changed hideKeyboard method as follows:

- (IBAction)hideKeyboard:(id)sender
{
    // Just call resignFirstResponder on all UITextFields and UITextViews in this VC
    // Why? Because it works and checking which one was last active gets messy.
    //UITextField * tf = (UITextField *) sender;
    [_textBeingEdited resignFirstResponder];
}
mtorre
  • 31
  • 5
2

One of the most easiest and shortest way is to add this code to your viewDidLoad

[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc]
                                     initWithTarget:self.view
                                     action:@selector(endEditing:)]];
Sudhin Davis
  • 2,010
  • 13
  • 18
2
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

    if let touch = touches.first{
     view.endEditing(true)

     }
}
Phani Sai
  • 1,215
  • 19
  • 33
1

This works

In this example, aTextField is the only UITextField.... If there are others or UITextViews, there's a tiny bit more to do.

// YourViewController.h
// ...
@interface YourViewController : UIViewController /* some subclass of UIViewController */ <UITextFieldDelegate> // <-- add this protocol
// ...
@end

// YourViewController.m

@interface YourViewController ()
@property (nonatomic, strong, readonly) UITapGestureRecognizer *singleTapRecognizer;
@end
// ...

@implementation
@synthesize singleTapRecognizer = _singleTapRecognizer;
// ...

- (void)viewDidLoad
{
    [super viewDidLoad];
    // your other init code here
    [self.view addGestureRecognizer:self.singleTapRecognizer];

{

- (UITapGestureRecognizer *)singleTapRecognizer
{
    if (nil == _singleTapRecognizer) {
        _singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapToDismissKeyboard:)];
        _singleTapRecognizer.cancelsTouchesInView = NO; // absolutely required, otherwise "tap" eats events.
    }
    return _singleTapRecognizer;
}

// Something inside this VC's view was tapped (except the navbar/toolbar)
- (void)singleTapToDismissKeyboard:(UITapGestureRecognizer *)sender
{
    NSLog(@"singleTap");
    [self hideKeyboard:sender];
}

// When the "Return" key is pressed on the on-screen keyboard, hide the keyboard.
// for protocol UITextFieldDelegate
- (BOOL)textFieldShouldReturn:(UITextField*)textField
{
    NSLog(@"Return pressed");
    [self hideKeyboard:textField];
    return YES;
}

- (IBAction)hideKeyboard:(id)sender
{
    // Just call resignFirstResponder on all UITextFields and UITextViews in this VC
    // Why? Because it works and checking which one was last active gets messy.
    [aTextField resignFirstResponder];
    NSLog(@"keyboard hidden");
}
1
- (void)viewDidLoad
{
    [super viewDidLoad]; 

UITapGestureRecognizer *singleTapGestureRecognizer = [[UITapGestureRecognizer alloc]
                                                          initWithTarget:self
                                                          action:@selector(handleSingleTap:)];
    [singleTapGestureRecognizer setNumberOfTapsRequired:1];
    [singleTapGestureRecognizer requireGestureRecognizerToFail:singleTapGestureRecognizer];

    [self.view addGestureRecognizer:singleTapGestureRecognizer];
}

- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
    [self.view endEditing:YES];
    [textField resignFirstResponder];
    [scrollView setContentOffset:CGPointMake(0, -40) animated:YES];

}
Gaurav Gilani
  • 1,584
  • 14
  • 18
1

You can use UITapGestureRecongnizer method for dismissing keyboard by clicking outside of UITextField. By using this method whenever user will click outside of UITextField then keyboard will get dismiss. Below is the code snippet for using it.

 UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
                                   initWithTarget:self
                                   action:@selector(dismissk)];

    [self.view addGestureRecognizer:tap];


//Method
- (void) dismissk
{
    [abctextfield resignFirstResponder];
    [deftextfield resignFirstResponder];

}
kender
  • 85,663
  • 26
  • 103
  • 145
Nirzar Gandhi
  • 79
  • 1
  • 8
1

In this case, there can be use ScrollView and added to TextField in ScrollView and I want Tap the ScrollView and View then Dismiss the Keyboard. I tried to create sample code just in case. Like this,

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var textField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.tap(_:)))
        view.addGestureRecognizer(tapGesture)
        // Do any additional setup after loading the view, typically from a nib.
    }
    func tap(gesture: UITapGestureRecognizer) {
        textField.resignFirstResponder()
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

Your Storyboard Look at that Just Like.

enter image description here

Ravi Dhorajiya
  • 1,531
  • 3
  • 21
  • 26
1
  • Set text fields delegate in view did load:

    override func viewDidLoad() 
    {
      super.viewDidLoad()
      self.userText.delegate = self
    }
    
  • Add this Function:

    func textFieldShouldReturn(userText: UITextField!) -> Bool 
    {
     userText.resignFirstResponder()
     return true;
    }
    
seggy
  • 1,176
  • 2
  • 18
  • 38
1

For those struggling with this in Swift. This is the accepted answer by Jensen2k but in Swift.

Swift 2.3

    override func viewDidLoad() {
        //.....

        let viewTapGestureRec = UITapGestureRecognizer(target: self, action: #selector(handleViewTap(_:)))
        //this line is important
        viewTapGestureRec.cancelsTouchesInView = false
        self.view.addGestureRecognizer(viewTapGestureRec)

         //.....
    }

    func handleViewTap(recognizer: UIGestureRecognizer) {
        myTextField.resignFirstResponder()
    }
lwdthe1
  • 1,001
  • 1
  • 16
  • 16
1

Send message resignFirstResponder to the textfiled that put it there. Please see this post for more information.

Community
  • 1
  • 1
1

There is one thing to important...

adding gesture recognize to view can subview override it.. So only one action is performed.. If you want to perform recognize multiple action through superview and subview... You have to use

 tap.cancelsTouchesInView = false

Full code is below:

 let tap = UITapGestureRecognizer(target: self, action: #selector(self.superViewClicked))
        tap.numberOfTapsRequired = 1
        tap.delegate = self
        tap.cancelsTouchesInView = false
        self.view.addGestureRecognizer(tap)




  @objc func superViewClicked(){
        
        self.searchTF.resignFirstResponder()
    }

What is best solution for dissmis soft keyboard on outside click?

I will explain for one condition:

Think about it : You have UISearchBar on the top, then tableview with header added!

Solution is simple:

  1. track soft keyboard is open or dismiss
  2. Add gesture recognize to header view
  3. implement delegate of table view didSelectRowAt

Full code:

   var isSoftKeyboardActive = false

    override func viewDidLoad() {
    
    
        var tap = UITapGestureRecognizer(target: self, action: #selector(self.tableHeaderClick))
            tap.numberOfTapsRequired = 1
            tap.delegate = self
            tap.cancelsTouchesInView = false
            self.headerOfTableView.addGestureRecognizer(tap)
    
    }
    
          override func viewWillAppear(_ animated: Bool) {
                  super.viewWillAppear(animated)
                 NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillDisappear), name: UIResponder.keyboardWillHideNotification, object: nil)
                  NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillAppear), name: UIResponder.keyboardWillShowNotification, object: nil)
              }
              
              override func viewWillDisappear(_ animated: Bool) {
                  super.viewWillDisappear(animated)
                  NotificationCenter.default.removeObserver(self)
              }
        


    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
          if isSoftKeyboardActive == true{
               
               self.searchTF.resignFirstResponder()
           }else{
           
               selectedRow = indexPath.row
               performSegue(withIdentifier: "segueWebview", sender: self)
               
           }
    }
    


 
    @objc func tableHeaderClick(){
         
        self.searchTF.resignFirstResponder()
    
     }
    
    
    
  @objc func keyboardWillAppear() {

        
        isSoftKeyboardActive = true
    }

    @objc func keyboardWillDisappear() {
        
        isSoftKeyboardActive = false
        
    }
 

How is it work:

  1. If soft keyboard is open and user click header soft keyboard close
  2. If soft keyboard is open and user click cell, keyboard close and no perform cell click
Ucdemir
  • 2,852
  • 2
  • 26
  • 44
0

just use this code in your .m file it will resign the textfield when user tap outside of the textfield.

 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
  [textfield resignFirstResponder];
 }
0
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
    super.view.endEditing(true)
    super.touchesBegan(touches, withEvent: event)
}
Derek Dawson
  • 502
  • 5
  • 14
0

So I just had to solve this very problem, and none of the previous answers worked for me out of the box. My situation: a UISearchBar, plus a number of other controls on the screen. I want for a tap outside of the search bar to dismiss the keyboard, but not propagate to any of the other controls. When the keyboard is hidden, I want all the controls to work.

What I did:

1) Implement a custom touch handler in my view controller.

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
{
    if searchBar.isFirstResponder()
    {
        // This causes the first responder, whoever it is, to resign first responder, and hide the keyboard.
        // We also "eat" the touch here and not allow it to propagate further.
        view.endEditing(true)
    }
    else
    {
        // OK to propagate the touch
        super.touchesBegan(touches, withEvent: event)
    }
}

2) Added a couple of delegate methods (mine are for the UISearchBar, but there are similar ones for UITextField). controlContainerView in the code below is a UIView that has a bunch of buttons in it. Remember that setting userInteractionEnabled on a superview disables all its subviews.

 func searchBarTextDidBeginEditing(searchBar: UISearchBar)
 {
     controlContainerView.userInteractionEnabled = false
     someButton.userInteractionEnabled = false
 }

 func searchBarTextDidEndEditing(searchBar: UISearchBar)
 {
     searchBar.resignFirstResponder()

    // Done editing: enable the other controls again.

    controlContainerView.userInteractionEnabled = false
    someButton.userInteractionEnabled = false
}
TotoroTotoro
  • 17,524
  • 4
  • 45
  • 76
0

In viewDidLoad swift 4.2 The code like this

let viewTap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action:#selector(dismissKeyboard))
        view.addGestureRecognizer(viewTap)
@objc func dismissKeyboard() {
        view.endEditing(true)
    }
Srinivasan_iOS
  • 972
  • 10
  • 12
0

For collection view:

// the keyboard follows the dragging touch off screen, and may be pulled upward again to cancel the dismiss
collectionView.keyboardDismissMode = .interactive
// dismisses the keyboard when a drag begins
collectionView.keyboardDismissMode = .onDrag
Andrey Volobuev
  • 862
  • 8
  • 11