Question

I have a UITableView that has 2 different customcell definitions. One is a single UITextField and the other has 4 UITextFields

userInteractionEnabled is manually set to enable cell level touch navigation, and I handle the UI interaction within didSelectRowAtIndexPath to the first responder to the relevant cell

This all worked fine when I was using just the one customcell (EditableCustomCell) with one UITextField (editableTextField), but now I have a customcell (LatLonCustomCell) with 4 UITextFields (degrees, minutes, seconds, cartesian), I cannot determine which field has been touched in order to set becomeFirstResponder

(currently I'm defaulting in the first textfield called degrees during debug)

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{      
  [prevField resignFirstResponder];
  prevField.userInteractionEnabled = NO;

  if(indexPath.section == kFirstSection && (indexPath.row == kLatitudeRow || indexPath.row == kLongitudeRow)) {
    LatLonCustomCell *customCell = (LatLonCustomCell *)[MyTableView cellForRowAtIndexPath:indexPath];
    currField = customCell.degrees; // need to set correct field here
  } else {
    EditableCustomCell *customCell = (EditableCustomCell *)[MyTableView cellForRowAtIndexPath:indexPath];
    currField = customCell.editableTextField;
  }

  currFieldIndexPath = [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];
  currField.userInteractionEnabled = YES;
  [currField becomeFirstResponder];

}

Was it helpful?

Solution

OK, so for those that come across this with the same or similar problem, I have finally made a breakthrough

I decided that I was going to need to capture the X/Y coordinates of the touch prior to the didSelectRowAtIndexPath being called. This way I could then determine which UITextField the touch occurred in by checking the touch against the "bounds" of the textfield

After some random searching, I found that a VERY easy way of capturing ANY touch event in the viewcontroller (as touchesBegan only occurred in the custom overridden UITableViewCell class and I knew not how to pass this back up the chain Cell > TableView > Scroll View > Controller)

By adding this to the viewDidLoad method:

UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
tapGesture.numberOfTapsRequired = 1;
// Pass the tap through to the UITableView
tapGesture.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:tapGesture];

This captures all touches, calling the handleTapGesture method

Then within this method it was simply a case of checking if the touch was within the bounds of the tableview, and if so, determine the indexPath for the point touched and then check against the bounds of the object required, below is a simplified version of what I came up with

-(void)handleTapGesture:(UITapGestureRecognizer *)tapGesture {

  CGPoint tapLoc = [tapGesture locationInView:self.tableView];

  if([MyTableView indexPathForRowAtPoint:tapLoc]) {
    // Tap still handled by the UITableView delegate method

    NSIndexPath *indexPath = [MyTableView indexPathForRowAtPoint:tapLoc];

    if(indexPath.section == 0 && (indexPath.row == kLatitudeRow || indexPath.row == kLongitudeRow)) {
      LatLonCustomCell *customCell = (LatLonCustomCell *)[MyTableView cellForRowAtIndexPath:indexPath];
      UIScrollView *scrollView = (UIScrollView *)self.view;
      CGRect rc;

      // Degrees
      rc = [customCell.degrees convertRect:[customCell.degrees bounds] toView:scrollView];

      if (tapLoc.x >= rc.origin.x && tapLoc.y >= rc.origin.y && tapLoc.x <= (rc.origin.x + rc.size.width) && tapLoc.y <= (rc.origin.y + rc.size.height)) {
        NSLog(@"touch within bounds for DEGREES");
        touchField = customCell.degrees;
      }

// Repeat for other textfields here ....

....

In my code I save the field within touchField, as within the didSelectRowAtIndexPath code, I am already handling prevField/currField values to control the enabling/disabling of userInteractionEnabled and to set the currField as becomeFirstReponder

Hope this proves helpful to someone :)

OTHER TIPS

In the past when I have needed to check if a text box has been touched I checked if YourTextField.text.length > 0. If it is you can set becomeFirstResponder. Hope this helps.

Have you thought about using NSNotificationCenter to request notifications for UITextFieldTextDidBeginEditingNotification?

in viewDidLoad

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldBeganEditing) 
                                             name:UITextFieldTextDidBeginEditingNotification object:nil];

and then something like

-(void) textFieldBegainEditing: (NSNotification*) notification {
  // [notification object] will be the UITextField
  // do what you need to do with it (resign, become first responder)
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top