Archive for February 2014

Extra space in grouped UITableView on iOS 7

So I noticed that there is a lot of extra space at the header and footer of my UITableView that is in my current project that I am updating to iOS 7. After some frustration, I finally put together this category that I hung off of UITableView:

- (void)ios7Check
{
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
    {
        self.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.bounds.size.width, 4.0f)];
        self.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.bounds.size.width, 4.0f)];
    }
}

Basically, all you have to do is call this from the viewDidLoad method of your view controller (or table view controller), and fire the ios7Check method like this:

[_theTableView ios7Check];  // if you have an instance variable pointing to your table view

or:

[self.tableView ios7Check];  // if your view controller is a UITableViewController

And you can adjust the spacing of the header and footer by changing the 4.0f values in the method above.

Here is what the grouped table view looks like without the code above, and with the code:

ios7-tableview-header-bigios7-tableview-header-small

EDIT: By the way, don’t try to set your tableHeaderView or tableFooterView frame to a height of 0.0f, as if you do then it just puts in the extra space. It must be that the Cocoa Touch framework sees that you have a zero height view, and just considers it as null. Even a height value of 0.1f is good enough, if you want a table view that cozies right up to the top with no space in between.

BTW, an anniversary farewell to Nelson Briles, who was a pitcher for the Pittsburgh Pirates (and other teams), and was a founding figure of the Pirates Fantasy Camp. Unfortunately he passed away on this day in 2005, so I did not get to meet him since my first Fantasy Camp was in 2011.

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.