By Hua-Ying


2010-02-23 19:26:50 8 Comments

I have a UITableView with UITextFields as cells. I would like to dismiss the keyboard when the background of the UITableView is touched. I'm trying to do this by creating a UIButton the size of the UITableView and placing it behind the UITableView. The only problem is the UIButton is catching all the touches even when the touch is on the UITableView. What am I doing wrong?

Thanks!

27 comments

@mixja 2010-11-09 10:42:57

This is easily done by creating a UITapGestureRecognizer object (by default this will detect a "gesture" on a single tap so no further customization is required), specifying a target/action for when the gesture is fired, and then attaching the gesture recognizer object to your table view.

E.g. Perhaps in your viewDidLoad method:

UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
[self.tableView addGestureRecognizer:gestureRecognizer];

And the hideKeyboard method might look like this:

- (void) hideKeyboard {
    [textField1 resignFirstResponder];
    [textField2 resignFirstResponder];
    ...
    ...
}

Note that the gesture is not fired when touching inside a UITextField object. It is fired though on the UITableView background, footer view, header view and on UILabels inside cells etc.

@Brian 2011-01-13 19:50:57

When I tried this I found it prevented the table from selecting cells :(. Awesome solution otherwise

@Zebs 2011-02-14 17:23:21

As a solution bellow points out you can make this work much better by setting: gestureRecognizer.cancelsTouchesInView = NO;

@mixja 2011-02-17 11:59:54

Interesting - I've only used this on tables where I'm editing data using textfields, switches and buttons, so didn't pick up that issue.

@Paul Lynch 2011-08-22 16:38:04

And don't forget to release the gestureRecognizer once it is attached to the tableView.

@Gobot 2012-02-27 21:59:46

For the hideKeyboard method, instead of communicating directly with the text fields you can do [self.view endEditing:NO];. From Apple docs: "This method looks at the current view and its subview hierarchy for the text field that is currently the first responder. If it finds one, it asks that text field to resign as first responder. If the force parameter is set to YES, the text field is never even asked; it is forced to resign."

@astuter 2013-10-07 06:08:14

using this way my "didSelectRowAtIndexPath" method is not getting called. any solution for this ??

@adnako 2014-10-23 12:47:50

It all works only if tap on a cell, if a cell is smaller then tableview and you tap not on a cell but inside a table view, the selector does not fire :(

@adnako 2014-10-23 13:00:42

My solution is add gesture recognizer to underlying view and disable user interaction with table view when keyboard appears and set it back when disappears.

@Michael Colonna 2019-03-22 13:27:47

Try this:

viewDidLoad(){

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

    tableView.addGestureRecognizer(tap)

}
//Calls this function when the tap is recognized.
@objc func dismissKeyboard() {

    //Causes the view (or one of its embedded text fields) to resign the first responder status.
    view.endEditing(true)

}

@bbeckford 2011-06-30 16:01:41

Firstly, listen for scrollViewWillBeginDragging in your UIViewController by adding the UIScrollViewDelegate:

In .h file:

@interface MyViewController : UIViewController <UIScrollViewDelegate> 

In .m file:

- (void)scrollViewWillBeginDragging:(UIScrollView *)activeScrollView {

    [self dismissKeyboard];

}

Then listen for other interactions:

- (void)setupKeyboardDismissTaps {

    UISwipeGestureRecognizer *swipeUpGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeUpGestureRecognizer.cancelsTouchesInView = NO;
    swipeUpGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp;
    [self.tableView addGestureRecognizer:swipeUpGestureRecognizer];

    UISwipeGestureRecognizer *swipeDownGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeDownGestureRecognizer.cancelsTouchesInView = NO;
    swipeDownGestureRecognizer.direction = UISwipeGestureRecognizerDirectionDown;
    [self.tableView addGestureRecognizer:swipeDownGestureRecognizer];

    UISwipeGestureRecognizer *swipeLeftGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeLeftGestureRecognizer.cancelsTouchesInView = NO;
    swipeLeftGestureRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
    [self.tableView addGestureRecognizer:swipeLeftGestureRecognizer];

    UISwipeGestureRecognizer *swipeRightGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeRightGestureRecognizer.cancelsTouchesInView = NO;
    swipeRightGestureRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
    [self.tableView addGestureRecognizer:swipeRightGestureRecognizer];


    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    tapGestureRecognizer.cancelsTouchesInView = NO;
    [self.tableView addGestureRecognizer:tapGestureRecognizer];

}

Then implement dismissKeyboard:

- (void)dismissKeyboard {

    NSLog(@"dismissKeyboard");

    [yourTextFieldPointer resignFirstResponder];

}

And if, like me, you wanted to dismiss the keyboard for a UITextField inside a custom table cell:

- (void)dismissKeyboard {

    NSLog(@"dismissKeyboard");

    CustomCellClass *customCell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
    [customCell.textFieldInCell resignFirstResponder]; 

}

Hope that helps anyone searching!!

@Authman Apatira 2012-09-23 01:30:15

This really needs more upvotes.

@Rajive Jain 2013-05-14 18:08:51

As UITableView is a subclass of UIScrollView, implementing one delegate method below provides an extremely easy, quick solution. No need to even involve resignFirstResponder since view hierarchy introspects and finds the current responder and asks it to resign it's responder status.

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self.view endEditing:YES];
}

And remember to add UIScrollViewDelegate to header file.

@atulkhatri 2015-12-11 05:40:19

This can be done through this one liner as pointed out by @Joe Masilotti if you are targeting iOS7 and above: self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;

@Islam Q. 2016-07-14 21:53:13

What happens if you tap on a textfield on the bottom of the screen which is supposed to scroll up to show the keyboard? - Your keyboard will be hidden.

@RobLabs 2017-11-26 20:11:30

Swift 4 — self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissMode.onDrag

@Ivan Smetanin 2017-10-30 09:57:06

There is Swift 3 version without blocking taps on cells.

In viewDidLoad() method:

let dismissKeyboardGesture = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard))
dismissKeyboardGesture.cancelsTouchesInView = false
tableView.addGestureRecognizer(dismissKeyboardGesture)

And hideKeyboard looks like this:

func hideKeyboard() {
    view.endEditing(true)
}

@EAMax 2018-03-05 08:13:26

Thank you, it works

@Şafak Gezer 2017-09-28 12:40:59

UITableView has a handy backgroundView property, with which I achieved this behavior without messing with cell selection, as shown below in Swift:

let tableBackTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard))
tableView.backgroundView = UIView()
tableView.backgroundView?.addGestureRecognizer(tableBackTapRecognizer)

@Dom Bryan 2016-07-28 19:24:19

tableView.keyboardDismissMode = .onDrag

@Ben 2016-01-25 08:41:35

You can also do it from Storyboard: enter image description here

@John 2017-06-18 16:40:03

Whatever I choose : Dismiss on drag, Dismiss Interactively, when I touch the table cell, it is selected. I am using Xcode 8, swift 3. please help

@MontiRabbit 2015-12-18 15:34:17

I had a UITableViewController and implementing touchesBegan:withEvent: didn't work for me.

Here's what worked:

Swift:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    view.endEditing(true)
}

Objective-C:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [self.view endEditing:YES];
}

@HotFudgeSunday 2016-08-18 14:21:38

Good idea, I like it.

@Biodave 2015-10-02 12:41:13

Here's the swift version for your coding pleasure:

It adds a tap gesture recognizer then dismisses the keyboard. No outlet for the TextField is required!

override func viewDidLoad() {
    super.viewDidLoad()
    view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "handleTap:"))
}

func handleTap(sender: UITapGestureRecognizer) {
    if sender.state == .Ended {
        view.endEditing(true)
    }
    sender.cancelsTouchesInView = false
}

@peacetype 2015-10-16 00:00:17

This works even with a custom tableViewCell! I've spent so much time trying to figure this out. Thank you so much! You are my hero. youtu.be/EqWRaAF6_WY

@mert 2014-09-24 07:45:08

@mixca's answer is very useful but what if i've something different from UITextField. I think best way to handle it by searching all subviews of main view with recursive function, check example below

- (BOOL)findAndResignFirstResponder {
if (self.isFirstResponder) {
    [self resignFirstResponder];
    return YES;
}

    for (UIView *subView in self.subviews) {
        if ([subView findAndResignFirstResponder]) {
            return YES;
        }
    }
    return NO;
}

and also you can put this method to your utility class and can use from tap gesture like @mixca's answer..

@mlabraca 2014-09-17 08:33:58

I've found a solution that works great.

Is needed to use the UIGestureRecognizerDelegate and the method – gestureRecognizer:shouldReceiveTouch:.

Add the gesture recognizer to the TableView as follows:

UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
tapGestureRecognizer.cancelsTouchesInView = NO;
tapGestureRecognizer.delegate = self;
[self.suggestedTableView addGestureRecognizer:tapGestureRecognizer];
[tapGestureRecognizer release];

Then, implement the shouldReceiveTouch delegate method to reject touches that are performed in UITableViewCell class. The hideKeyboard method only will be called when the touch has been performed outside UITableViewCell class.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if([touch.view isKindOfClass:[UITableViewCell class]]) {
        return NO;
    }
    // UITableViewCellContentView => UITableViewCell
    if([touch.view.superview isKindOfClass:[UITableViewCell class]]) {
        return NO;
    }
    // UITableViewCellContentView => UITableViewCellScrollView => UITableViewCell
    if([touch.view.superview.superview isKindOfClass:[UITableViewCell class]]) {
        return NO;
    }
    return YES; // handle the touch
}

- (void) hideKeyboard{
    [textField resignFirstResponder];
}

@Kamel 2014-08-06 04:55:43

Here's how I finally made works. I combined suggestions and codes from different answers. Features: dismissing keyboard, moving text fields above keyboard while editing and setting "Next" and "Done" keyboard return type.REPLACE "..." with more fields

static const CGFloat ANIMATION_DURATION = 0.4;
static const CGFloat LITTLE_SPACE = 5;
CGFloat animatedDistance;
CGSize keyboardSize;

@interface ViewController () <UITextFieldDelegate>
 @property (weak, nonatomic) IBOutlet UITextField *firstNameTXT;
  .....// some other text fields
 @property (weak, nonatomic) IBOutlet UITextField *emailTXT;
@end

@implementation ViewController
- (void)viewDidLoad{
.....
// add tap gesture to help in dismissing keyboard
UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc]
                                       initWithTarget:self
                                       action:@selector(tapScreen:)];// outside textfields

[self.view addGestureRecognizer:tapGesture];

// set text fields return key type to Next, last text field to Done
[self.firstNameTXT setReturnKeyType:UIReturnKeyNext];
.....
[self.emailTXT setReturnKeyType:UIReturnKeyDone];

// set text fields tags
[self.firstNameTXT setTag:0];
....// more text fields
[self.emailTXT setTag:5];

// add keyboard notification
[[NSNotificationCenter defaultCenter] addObserver:self     selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
}
[[NSNotificationCenter defaultCenter] addObserver:self      selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
}

// dismiss keyboard when tap outside text fields
- (IBAction)tapScreen:(UITapGestureRecognizer *)sender {
  if([self.firstNameTXT isFirstResponder])[self.firstNameTXT resignFirstResponder];
  ...
  if([self.emailTXT isFirstResponder])[self.emailTXT  resignFirstResponder];

  }
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
   if(textField.returnKeyType==UIReturnKeyNext) {
     // find the text field with next tag
     UIView *next = [[textField superview] viewWithTag:textField.tag+1];
     [next becomeFirstResponder];
   } else if (textField.returnKeyType==UIReturnKeyDone || textField.returnKeyType==UIReturnKeyDefault) {
    [textField resignFirstResponder];
 }
return YES;
}

// Moving current text field above keyboard
-(BOOL) textFieldShouldBeginEditing:(UITextField*)textField{
   CGRect viewFrame = self.view.frame;
   CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField];
   CGRect viewRect = [self.view.window convertRect:self.view.bounds fromView:self.view];
   CGFloat textFieldBottomLine = textFieldRect.origin.y + textFieldRect.size.height + LITTLE_SPACE;//

   CGFloat keyboardHeight = keyboardSize.height;

   BOOL isTextFieldHidden = textFieldBottomLine > (viewRect.size.height - keyboardHeight)? TRUE :FALSE;
  if (isTextFieldHidden) {
    animatedDistance = textFieldBottomLine - (viewRect.size.height - keyboardHeight) ;
    viewFrame.origin.y -= animatedDistance;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:ANIMATION_DURATION];
    [self.view setFrame:viewFrame];
    [UIView commitAnimations];
  }
  return YES;
}

-(void) restoreViewFrameOrigionYToZero{
  CGRect viewFrame = self.view.frame;
  if (viewFrame.origin.y != 0) {
    viewFrame.origin.y = 0;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:ANIMATION_DURATION];
    [self.view setFrame:viewFrame];
    [UIView commitAnimations];
  }
}

-(void)keyboardDidShow:(NSNotification*)aNotification{
   NSDictionary* info = [aNotification userInfo];
   keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
 }

-(void)keyboardDidHide:(NSNotification*)aNotification{
   [self restoreViewFrameOrigionYToZero];// keyboard is dismissed, restore frame view to its  zero origin
}
@end

@Shawn Throop 2014-05-28 00:43:14

Simply using a UITapGestureRecognizer and cancelsTouchesInView = NO means that taps on cells and UITextViews also trigger the hide. This is bad if you have multiple UITextViews and you tap on the next one. The keyboard will start to hide and then the next textView becomes the firstResponder and the keyboard becomes visible again. To avoid this, check the tap location and only hide the keyboard if the tap isn't on a cell:

// init
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapTableView:)];
tapRecognizer.cancelsTouchesInView = NO;
[self.tableView addGestureRecognizer:tapRecognizer];


// Hide on tap
- (void)didTapTableView:(UITapGestureRecognizer *)tap
{
    CGPoint point = [tap locationInView:tap.view];
    [self.view endEditing:!CGRectContainsPoint([self.tableView rectForRowAtIndexPath:[self.tableView indexPathForRowAtPoint:point]], point)];
}

In order for scrollViewWillBeginDragging: to be triggered, the tableView's scrollEnabled property must be YES

// Hide on scroll
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self.view endEditing:YES];
}

@Nicola 2014-11-10 20:27:24

Perfect for me. Added a texbox to tableview cell; if I touch outside the keyboard dismiss

@Robertibiris 2014-05-23 11:26:52

Many interesting answers. I would like to compile different approaches into the solution that i thought best fit a UITableView scenario (it's the one I usually use): What we usually want is basically to hide the keyboard on two scenarios: on tapping outside of the Text UI elements, or on scrolling down/up the UITableView. The first scenario we can easily add via a TapGestureRecognizer, and the second via the UIScrollViewDelegate scrollViewWillBeginDragging: method. First order of business, the method to hide the keyboard:

   /**
     *  Shortcut for resigning all responders and pull-back the keyboard
     */
    -(void)hideKeyboard
    {
        //this convenience method on UITableView sends a nested message to all subviews, and they resign responders if they have hold of the keyboard
        [self.tableView endEditing:YES];

    }

This method resigns any textField UI of the subviews within the UITableView view hierarchy, so it's more practical than resigning every single element independently.

Next we take care of dismissing via an outside Tap gesture, with:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self setupKeyboardDismissGestures];

}

- (void)setupKeyboardDismissGestures
{

//    Example for a swipe gesture recognizer. it was not set-up since we use scrollViewDelegate for dissmin-on-swiping, but it could be useful to keep in mind for views that do not inherit from UIScrollView
//    UISwipeGestureRecognizer *swipeUpGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
//    swipeUpGestureRecognizer.cancelsTouchesInView = NO;
//    swipeUpGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp;
//    [self.tableView addGestureRecognizer:swipeUpGestureRecognizer];

    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
    //this prevents the gestureRecognizer to override other Taps, such as Cell Selection
    tapGestureRecognizer.cancelsTouchesInView = NO;
    [self.tableView addGestureRecognizer:tapGestureRecognizer];

}

Setting tapGestureRecognizer.cancelsTouchesInView to NO is to avoid the gestureRecognizer from overriding the normal inner workings of the UITableView (for example, not to interfere with cell Selection).

Finally, to handle hiding the keyboard on Scrolling up/down the UITableView, we must implement the UIScrollViewDelegate protocol scrollViewWillBeginDragging: method, as:

.h file

@interface MyViewController : UIViewController <UIScrollViewDelegate>

.m file

#pragma mark - UIScrollViewDelegate

-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self hideKeyboard];
}

I hope it helps! =)

@Sam 2014-01-09 18:38:55

I wanted my cell to open the keyboard when any part of the cell was selected and close it if you clicked anywhere off the cell. To open the keyboard:

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];
    if (selected)
    {
        [self.textField becomeFirstResponder];
    }
}

(NOTE: I've subclassed the cell but you can easily achieve this in the tableView:didSelectRowAtIndexPath: delegate method of UITableView)

Doing this meant that with the top solutions if you clicking on the cell twice the keyboard would shake as, first the gesture recogniser tried to close the keyboard, and second the cell was reselected and tried open the keyboard.

Solution is to check whether the click occurred inside the currently selected cell:

- (void)viewDidLoad
{
    [super viewDidLoad];
    //gesture recognizer to close the keyboard when user taps away
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                          action:@selector(dismissKeyboard:)];
    tap.cancelsTouchesInView = NO;
    [self.tableView addGestureRecognizer:tap];
}

-(void)dismissKeyboard:(UIGestureRecognizer*)tapGestureRecognizer
{
    if (!CGRectContainsPoint([self.tableView cellForRowAtIndexPath:[self.tableView indexPathForSelectedRow]].frame, [tapGestureRecognizer locationInView:self.tableView]))
    {
        [self.view endEditing:YES];
    }
}

@Saad 2012-02-29 08:14:04

Here is a best way to do this. Just do this

[self.view endEditing:YES];

or

[[self.tableView superView] endEditing:YES];

@John 2017-06-18 16:49:13

where should I put this code ? sorry I am beginner. And please provide swift code.

@Joe Masilotti 2014-01-04 18:15:36

If you are targeting iOS7 you can use one of 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 from UIScrollView, which UITableView inherits from.

@Sam 2014-01-09 19:06:50

nice. i manageds to sort-of break it by swiping down from high up the screen until the keyboard started to move down, then swiping back up until the keyboard moved up a little, then letting go. the scrollview doesn't spring back to the top as it should.

@sha 2010-02-23 19:38:43

I did it like this:

Create a method in your TableViewController to deactivate first responder (which would be your TextBox at that point)

- (BOOL)findAndResignFirstResonder:(UIView *)stView {
    if (stView.isFirstResponder) {
        [stView resignFirstResponder];
        return YES;     
    }

    for (UIView *subView in stView.subviews) {
        if ([self findAndResignFirstResonder:subView]) {
            return YES;
        }
    }
    return NO;
}

In tableView:didSelectRowAtIndexPath: call the previous method:

- (void)tableView:(UITableView *)tableView
                             didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    ...
    [self findAndResignFirstResonder: self.view];
    ...
}

@Hua-Ying 2010-02-23 19:41:55

This will dismiss the keyboard but it isn't what I'm asking for...

@user177800 2010-02-23 20:02:41

you are doing it wrong the way you are asking. you don't put a button on the view you tell the view to remove the keyboard like this answer says

@Joe D'Andrea 2010-05-11 22:31:09

This works beautifully if you tap within a table view cell (and outside of any UITextField within that table view cell). However, if I tap the background of the table view (which is often an easier target to get at - yay Fitts's Law!), no such luck. True, that's expected, since we're performing this operation within tableView:didSelectRowAtIndexPath:. If this can be adjusted somehow to work with tapping anywhere else in the table view (that wouldn't otherwise want keyboard focus), I think we've got a winner here!

@zekel 2010-06-30 19:21:58

I have the same problem as jdandrea. That didSelectRowAtIndexPath doesn't fire if you tap the TableView itself.

@Amogh Talpallikar 2012-12-11 09:26:59

if didSelectRowAtIndexPath is not sufficient, do the same in touchesBegan as well!

@hac.jack 2012-05-22 06:01:35

I had the same problem and here's my solution, it works perfectly for me:

In the view or view controller that you implemented <UITextFieldDelegate>

(In my case I have a custom UITableViewCell called TextFieldCell),

Declare the UITapGestureRecognizer as a property:

@interface TextFieldCell : UITableViewCell <UITextFieldDelegate>
{
    UITextField *theTextField;
    UITapGestureRecognizer *gestureRecognizer;
}
@property (nonatomic,retain) UITextField *theTextField;
@property (nonatomic,retain) UITapGestureRecognizer *gestureRecognizer; 

And initialize it in your view/controller:

self.gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeKeyboard:)];

In the - (void)textFieldDidBeginEditing:(UITextField *)textField method, use superView to move up to your tableView and call addGestureRecognizer:

[self.superview.superview addGestureRecognizer:gestureRecognizer];

And in the - (void)textFieldDidEndEditing:(UITextField *)textField, just remove the gesture recognizer:

[self.superview.superview removeGestureRecognizer:gestureRecognizer];

Hope it helps.

@gilsaints88 2013-01-19 15:44:48

This did it for me. Thanks hac.jack

@Eshwar Chaitanya 2012-02-18 07:30:28

If you want to dismiss the keyboard while return key is pressed,you can simply add the following code in textField should return method i.e.:

- (BOOL)textFieldShouldReturn:(UITextField *)atextField
{
   [textField resignFirstresponder];
}

Some textfields might have a picker view or some other as a subview,so in that case the above method doesn't work so in that case we need to make use of UITapGestureRecognizer class i.e. add the following code snippet to viewDidLoad method i.e.:

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

    [self.view addGestureRecognizer:tap];

Now simply add the resign responder to the selector method i.e.:

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

Hope it helps,thanks :)

@Miro Hudak 2011-11-23 03:54:05

I was searching for the solution and did not find anything that would fit my code, so I did it like this:

http://82517.tumblr.com/post/13189719252/dismiss-keyboard-on-uitableview-non-cell-tap

It's basically a combination of before-mentioned approaches but does not require to subclass anything or to create background buttons.

@Sam 2014-01-09 18:14:59

your code vanished :(

@Azbuky 2011-01-18 18:21:28

The UITapGestureRecognizer solution works with table cell selection if you set:

gestureRecognizer.cancelsTouchesInView = NO;

@onmyway133 2016-08-02 07:03:32

This allows touching the cell, but the gesture is recognized as well, perhaps we should implement this delegate methods shouldReceiveTouch

@pschang 2010-08-28 18:31:57

UITableView is a subclass of UIScrollView.

The way I did it was to listen for a scroll event by the user and then resignFirstResponder. Here's the UIScrollViewDelegate method to implement in your code;

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView

When approaching these sorts of problems I've found the best way is to research the delegate protocols for each object and those of the parent classes (in this case UITableViewDelegate, UIScrollViewDelegate. The number of events NS objects fires is quite large and comprehensive. It's also easier implementing a protocol then subclassing anything.

@bandejapaisa 2010-08-18 11:46:43

@interface DismissableUITableView : UITableView {
}
@end

@implementation DismissableUITableView

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

@end

Then make sure that in your Nib file you set the type of your UITableView to DismissableUITableView .....maybe i could have thought of a better name for this class, but you get the point.

@Joe D'Andrea 2010-05-11 22:44:48

If you're willing to subclass (ugh!) your table view, something like this might work:

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

   BOOL backgroundTouched = YES;

   for (UITouch *touch in touches) {
      CGPoint location = [touch locationInView:self];
      for (UITableViewCell *cell in self.visibleCells) {
         if (CGRectContainsPoint(cell.frame, location)) {
            backgroundTouched = NO;
            break;
         }
      }
   }

   if (backgroundTouched) {
      for (UITableViewCell *cell in self.visibleCells) {
         // This presumes the first subview is the text field you want to resign.
         [[cell.contentView.subviews objectAtIndex:0] resignFirstResponder];
      }
   }

   [super touchesBegan:touches withEvent:event];
}

@Mugunth 2010-02-25 07:13:52

Why do you want to create a table full of textfields? You should be using a detailed view for each row that contains the text fields. When you push your detailedview, ensure that you call "[myTextField becomeFirstResponder]" so that the user can start editing with just one click away from the table list.

@Joe D'Andrea 2010-05-11 22:31:33

Apple's Contacts app does precisely this. I wouldn't say it's full of text fields per se, but it does use them to good effect.

@glenc 2010-10-16 13:57:18

Editing text inline in a tableview is much quicker and more intuitive than pushing detail views for every text field the user wants to edit ... just ask your nearest HTML form, or the text fields in iPhone Preferences panes, or the Contacts app, or etc etc etc ... it's a real shame that Apple hasn't made this a standard cell type, but there is much info on the web about achieving this.

Related Questions

Sponsored Content

17 Answered Questions

38 Answered Questions

[SOLVED] How can I disable the UITableView selection?

26 Answered Questions

92 Answered Questions

40 Answered Questions

[SOLVED] Move view with keyboard using Swift

46 Answered Questions

[SOLVED] Making a UITableView scroll when text field is selected

35 Answered Questions

[SOLVED] iOS - Dismiss keyboard when touching outside of UITextField

9 Answered Questions

[SOLVED] How to hide keyboard on touch UITableView in iOS Obj-C

2 Answered Questions

[SOLVED] Keyboard dismiss and UITableView touch issue

3 Answered Questions

[SOLVED] Dismissing keyboard on tapping outside the table

Sponsored Content