16

I'm not sure why this is so hard. I have a UISearchBar at the top of my page. When the user types into that UISearchBar, it will automatically filter the results in the UITableView that is below the search bar. There is no need for a Search button since I search when keys are pressed.

The flow of the application is that the user types a search in the search bar (with the keyboard being displayed) and then will scroll the results in the table view - at which point the keyboard needs to disappear.

I'm having a hard time getting the keyboard to disappear.

I know I need to do:

    [searchBar resignFirstResponder];

to get the keyboard to disappear but I can't find what delegate I need to perform this on. I want to do this as soon as the user touches the table view.

Any ideas?

rein
  • 32,967
  • 23
  • 82
  • 106
  • Check this: http://stackoverflow.com/questions/7482266/resign-keyboard-when-losing-focus-on-uisearchbar – 0xKayvan Nov 08 '14 at 20:59

7 Answers7

10

Try this:

- (void)viewWillDisappear:(BOOL)animated {

    [super viewWillDisappear:animated];

    [searchBar resignFirstResponder];

}

It worked for me

Frank Krueger
  • 69,552
  • 46
  • 163
  • 208
H Vargas
  • 101
  • 1
  • 2
2

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 also better than using a dim screen because in a complexe and dynamic user interface, you can't put dim screen every where. Also, it's better than calling [searchBar resignFirstResponder], because you may have many text fields on screen, so this works for all of them.

Enzo Tran
  • 5,750
  • 6
  • 31
  • 36
1

Since the results are going to be in a table view, use UIScrollView's delegate (to which UITableView responds) method - (void)scrollViewDidScroll:(UIScrollView *)scrollView.

You'll need to have your view controller respond to the UITableView's data source and delegate (in the .h file):

<UITableViewDataSource, UITableViewDelegate>

Than in your initialization method in the .m file add:

self.tableView.dataSource = self;
self.tableView.delegate = self;

Finally, add this method:

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

This will make the UISearchBar lose focus, and the keyboard will hide.

nikolovski
  • 4,049
  • 1
  • 31
  • 37
1

One possibility is that the UISearchBar belongs to a controller, that is displayed in UIModalPresentationFormSheet. I had the same problem and found out that this is related to the method "disablesAutomaticKeyboardDismissal" of UIViewController.

The Apple documentation states the following:

Override this method in a subclass to allow or disallow the dismissal of the current input view (usually the system keyboard) when changing from a control that wants the input view to one that does not. Under normal circumstances, when the user taps a control that requires an input view, the system automatically displays that view. Tapping in a control that does not want an input view subsequently causes the current input view to be dismissed but may not in all cases. You can override this method in those outstanding cases to allow the input view to be dismissed or use this method to prevent the view from being dismissed in other cases.

The default implementation of this method returns YES when the modal presentation style of the view controller is set to UIModalPresentationFormSheet and returns NO for other presentation styles. Thus, the system normally does not allow the keyboard to be dismissed for modal forms.

In my case, I displayed the search bar within the navigation bar, so I had to create a subclass of UINavigationViewController that overrides the method as follows:

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

After that resignFirstResponder would finally make the keyboard disappear.

Albz
  • 1,982
  • 2
  • 21
  • 33
Nostradani
  • 21
  • 2
1

You might want to do it as Cydia (jailbroken packaging UI) does it - there is a search button, and when you press the search button, it closes the keyboard. The results are still filtered as you type for a preview.

Isaac Waller
  • 32,709
  • 29
  • 96
  • 107
  • 1
    This would necessitate the pressing of the search button to remove the keyboard - a step that I feel should be unnecessary and might just frustrate users. Thanks though. – rein May 20 '09 at 14:54
0

Might be super late to answer but this might help anyone in future. This particular piece of code worked for me. P.S. I don't own this solution, found some time ago on the net itself.

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
if ([self.srchBar isFirstResponder] && [touch view] != self.srchBar)
{
    [self.srchBar resignFirstResponder];
}   
[super touchesBegan:touches withEvent:event];
}
treatheat
  • 41
  • 4
0

Given a view with a searchBar variable, add this method to the view:

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?
{
    if searchBar.isFirstResponder && !searchBar.point(inside: point, with: event){
        searchBar.resignFirstResponder()
    }
    return super.hitTest(point, with: event)
}
Jano
  • 62,815
  • 21
  • 164
  • 192