Archive for 7th February 2014

Determine which UITableViewCell contains a specified UIControl

If you have UITextField controls inside of a table view cell, and you are hooked into one of the UITextFieldDelegate methods, then you might need to determine which UITableViewCell contains a specified UIControl inside of a delegate method.

The wrong way

Up until now, I have always taken the shortcut of just walking back to the grandparent of the control by doing something like this:

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
    UITableViewCell *cell = (UITableViewCell *)textField.superview.superview;
 
    // do something here with the cell
 
    return YES;
}

However, when building and running under the iOS 7 SDK, this of course does not work any more.

The right way

After researching this phenomenon a bit more, I found a solution that does not rely on walking the view hierarchy, which by the way kids, is usually never a good idea. Here is a category that I built on top of UIView:

- (UITableViewCell *)findParentCellInTableView:(UITableView *)tableView
{
    UITableViewCell *cell = [self findParentUITableViewCell];
    return cell;
}
 
- (UITableViewCell *)findParentUITableViewCell
{
    if (self.superview && [self.superview isKindOfClass:[UITableViewCell class]])
    {
        return (UITableViewCell *)self.superview;
    }
 
    return [self.superview findParentUITableViewCell];
}

As a result, now my delegate call looks like this:

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
    UITableViewCell *cell = [textField findParentCellInTableView:tableView];
 
    // do something here with the cell
 
    return YES;
}

Since I built this category off of UIView, it will work with most common items built on top of UIView or UIControl that you would put in a table view cell, such as UILabel, UITextField, UITextView, etc.

BTW, Happy Anniversary to The Beatles, who first visited the United States 50 years ago today.

EDIT: My first attempt to create the findParentCellInTableView method ended in disaster, as I forgot to take into account the fact that table view cells can scroll off the screen and possible get reused. As a result, I created a method that walks up the view chain more intelligently than simply going to the superview’s superview. As always, please let me know if you have any comments.