Reputation: 64844
I have a UITableView with a UITextField for each row. When the user touches outside the tableview, deselecting the text field, I would like to invoke a method.
However, I don't want to invoke such method if the user selects another row of the table.
thanks
**Code for alloc_iNit **:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
CMTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CMTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
[[cell textField] setTag:[indexPath row]];
[[cell textField] setDelegate:self];
NSString *tagName = [tagsDisplayName objectAtIndex:[indexPath row]];
[[cell textField] setText:tagName];
return cell;
}
Upvotes: 1
Views: 2588
Reputation: 91
I ended up with 2 tap events + added "becomeFirstResponder" on my table so clicking on it won't make it hidden
myTableView.isUserInteractionEnabled = true
myTableView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(searchTableTapEvent(_:))))
myTableView.becomeFirstResponder()
rootView.isUserInteractionEnabled = true
rootView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tapOutsideEvent(_:))))
}
@objc func searchTableTapEvent(_ sender: UITapGestureRecognizer? = nil) {
Log.debug("searchTableTapEvent")
}
@objc func tapOutsideEvent(_ sender: UITapGestureRecognizer? = nil) {
Log.debug("rootViewTapEvent")
myTableView.isHidden = true
}
Upvotes: 0
Reputation: 41642
FIRST SUGGESTION:
I believe the system will help you on this, as it didn't help me (I had to work around it). If you have two textfields, and you have one open, and tap a different one, then the second one gets
textFieldDidShouldBeginEditing:
BEFORE the original one is sent:
textFieldDidEndEditing: // or textFieldShouldEndEditing
Add a couple of log messages to your project to verify this, and if is not so then it may be some other message. It was a year ago I had a problem because of the apparent disordering.
2012-08-30 09:22:40.528 Searcher[22053:f803] SHOULD BEGIN // first tap on first textField
2012-08-30 09:22:40.534 Searcher[22053:f803] BEGIN
2012-08-30 09:22:42.168 Searcher[22053:f803] SHOULD BEGIN // second tap on second TF
2012-08-30 09:22:42.168 Searcher[22053:f803] SHOULD END
2012-08-30 09:22:42.170 Searcher[22053:f803] END
SECOND SUGGESTION:
The user can tap the view anywhere, but if they tap the same textfield (to get copy/paste) you don't want to dismiss.
create a new ivar that stores the textField when it gets 'textFieldDidShouldBeginEditing':
__block UITextField *currTextField;
put a transparent view over your view (excluding the keyboard) that detects touch events
when the transparent view sees the touch event, if no textField set or the touch is inside the original touchView, do nothing
if the touch is anywhere else, and there is a currentTextField, forward the event, then dispatch a block to the mainQueue as follows:
UITextField *lastTextField = currTextField; dispatch_async(dispatch_get_main_queue(), ^{ if(currTextField && currTextField == lastTextField) { [currTextField resignFirstResponder]; // touch outside the textField, but no new one } } );
Upvotes: 0
Reputation: 1540
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
if(activeTextField) //declare it in .h file
[self textFieldDidEndEditing:activeTextField];
activeTextField = textField;
CGRect textViewRect = [tableView convertRect:activeTextField.bounds fromView:activeTextField];
[tableView scrollRectToVisible:textViewRect animated:NO]; //if u want to add scroll to that cell
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
activeTextField = nil;
}
and then u can use touchesBegan
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[activeTextField resignFirstResponder];
}
hope this one helps. happy coding :)
Upvotes: 0
Reputation: 3001
Something to consider would be using a Tap Gesture recognizer on the view behind the UITableView. You might have to play around with the shouldReceiveTouch event (elaborated on in Gesture recognizer and button actions) to keep the Tap Gesture Recognizer from firing when you click somewhere in the UITableView.
Upvotes: 2
Reputation: 5183
You have to override hitTest:withEvent: on the actual UITableView itself. Remember that it takes control of the responder chain, so the subviews won’t get a chance to handle it first, unless we explicitly override that behavior
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { return [super hitTest:point withEvent:event]; }
hitTest:withEvent: is responsible for telling the system which view that was hit, by default UITableView assumes itself (or one of its cells), so you have to figure out if the user touches locations, and if user touches outside the tableview so return that view instead.
Modified Code:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { NSLog(@"hitTest"); UIView *subview = [super hitTest:point withEvent:event]; if (event.type == UIEventTypeTouches) { // get touches NSSet *touches = [event allTouches]; NSLog(@"subview: %@", subview); NSLog(@"touches: %@", touches); } }
Upvotes: 0