I have a UIView with a UITextField, UIButton and UITable view. The textfield and button compromise a search bar and the results are then loaded into the table view.
I'd like to make it so they keyboard dismisses. If the user taps something when they are editing the text field. My strategy would be to add a gesture recognizer to the UIView, but then gesture recognizer seems to intercept all the touches from the table view and you |tableView:didSelectCellAtIndexPath:| never gets called. Whats interesting (to me at least) is that the UIButton is still tap-able when the user is editing the field even though the UITableView isn't.
I've tried implementing |gestureRecognizer::shouldRecognizeSimultaneouslyWithGestureRecognizer:| to alway return yes, but that doesn't help. I've also tried setting
singleTapRecognizer.cancelsTouchesInView = NO;
which also doesn't help.
I'm happy with the idea of adding and removing the gesture recognizer when the text field calls |textFieldDidBeginEditing:| and |textFieldDidFinishEditing:|, though this feels messy and it still takes two taps to touch a cell when you're editing the text field (one to dismiss they keyboard and remove the recognizer, and one to tap the cell).
Is there a better way?
Relevant code below:
- (void)loadView {
[super loadView];
self.scrollView = [[UIScrollView alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.scrollView.backgroundColor = [FDEColors viewBackgroundColor];
self.view = self.scrollView;
self.searchField = [[UITextField alloc] initWithFrame:CGRectZero];
self.searchField.placeholder = @"What are you looking for?";
self.searchField.backgroundColor = [FDEColors textFieldBackgroundColor];
self.searchField.clipsToBounds = YES;
self.searchField.layer.borderColor = [[FDEColors buttonColor] CGColor];
self.searchField.layer.borderWidth = 1.f;
self.searchField.returnKeyType = UIReturnKeySearch;
self.searchField.delegate = self;
[self.view addSubview:self.searchField];
self.searchButton = [[UIButton alloc] initWithFrame:CGRectZero];
self.searchButton.backgroundColor = [FDEColors buttonColor];
[self.searchButton setTitle:@"Search" forState:UIControlStateNormal];
[self.searchButton addTarget:self
action:@selector(searchPressed:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.searchButton];
self.resultsTableView =
[[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
self.resultsTableView.delegate = self;
self.resultsTableView.dataSource = self;
self.resultsTableView.backgroundColor = [FDEColors viewBackgroundColor];
[self.resultsTableView setSeparatorInset:UIEdgeInsetsZero];
self.resultsTableView.layoutMargins = UIEdgeInsetsZero;
[self.resultsTableView registerClass:[FDESearchResultsCell class]
forCellReuseIdentifier:[FDESearchResultsCell reuseIdentifier]];
[self.view addSubview:self.resultsTableView];
self.singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(dismissKeyboard)];
[self.view addGestureRecognizer:self.singleTapRecognizer];
}
- (void)dismissKeyboard {
[[self view] endEditing:YES];
}
Try implementing the gesture recognizer's delegate method:
In this method, check for the touch's location. If it's inside the tableview, return no, so the tableview can receive the touch. Otherwise, return YES and let the recognizer handle the touch.
Edit: As for the button receiving the touch despite the recognizer's existence, as of iOS6 Apple decided to give buttons and some other controls priority when it comes to recognizing gestures. It only applies to antagonizing gestures though, in your case a single tap. If for example you also had a pan recognizer, the recognizer would have precedence, not the button.
Edit 2:
An example implementation of the method mentioned above:
}