Michael Olivero
The official blog of Michael Olivero, Software Architect & Humble Entrepreneur

Setting UITableView rowHeight property dynamically when reusing UITableViewCell via xib / nib

Monday, 1 October 2012 14:07 by Michael Olivero

xCode allows for multiple convenient ways for configuring the UITableView cells.  Using one of default custom configurations, specifying it in storyboard as a prototype, specifying it in a nib file which is then reused, and simply creating it in code directly.  While developing an app which makes use of the UITableView, I came across an interesting dilemma where I wanted the flexibility of using xCode's UI to configure it however I wanted to avoid certain issues each approach carries as described below.

One approach is to define each UITableViewCell as a prototype of each UITableView directly in storyboard as shown below,

however if there are going to be multiple UITableViews displaying cells in a similar fashion, the inclination is to configure them repeatedly in each UITableView.  This is very repetitious and may even lead to inconsistencies if one is not careful and generally is considered bad programming practice similar to copying a pasting an entire method just to make one small modification within.  One can improve upon this approach by inheriting a common base UITableView class where the configuration is specified in code, however this defeats the flexibility of using xCode's UI to custom configure the UITableViewCell's various sub views.

Another approach is defining the UITableViewCell in a separate nib / xib file, you can then register the nib and reference the UITableViewCell for reuse accordingly from any UITableView controller.  This method retains the configurability of the UITableViewCell via the xCode interface as shown below.

 

When reusing the UITableView cell in this fashion however, most online examples indicate to register the nib file for reuse and then dequeue as usual to populate the data for each individual cell.  The problem here is, the UITableView's rowHight property is not updated automatically as it is when one specifies the UITableViewCell as a prototype and at run time, you may see something like this:

 

 

Many online blogs emphasize the height should be specified as part of the cell construction while executing with the cellForRowAtIndexPath method within the UITableViewController.  The problem I have with this solution is quite frankly, even though perhaps only 10 or actual cells will be constructed and then reused, this code is repeated unnecessarily for those 10 or so times.

The easier route is simply to specify a fixed height in the nib file, say 60 and then specifying the same 60 points in the UITableView's rowHeight property as shown in both images below.

 

 

 This will produce the balanced height we are seeking as shown below:

 

While this has improvements on reuse as we will have consistently looking UITableViewCell's throughout our various controllers and retains the ability to configured and edited via the xCode UI, it still has the ill effect of having to maintaing the rowHeight in two or more different places whenever the height changes and is not yet to my satisfaction of cleanliness.

Further research online reveal many blogs emphasizing the implementation of the heightForRowAtIndexPath method for the UITableViewController. This method is great when there are UITableViewCells with dynamically varying content which need varying height for each cell, however this is not the case here. The problem with this approach continues to be the repeated calls for a UITableViewCell which doesn't vary in height.  Furthermore, in the various examples I found not only is the height specified repeatedly, but registration of nib is repeated as well and some additional lines of code which could also be avoided.

 

The Solution:

Since in this particular example, the UITableViewCell height will remain the same across all sections and rows and UITableViews, it makes sense to programmatically tell the UITableView it's rowHeight much like we would via the xCode UI, however do so once and be done with it.  The value should also be extracted programmatically from the UITableViewCell residing in the nib / xib file so if the height is ever changed in the future via the design tools, the UITableView is automatically adjusted accordingly without any further intervention in the code.

To accomplish this, the logical place to put such code would be in the UiTableViewController's viewDidLoad method as this code is executed once regardless of the number of rows to rendered.  In this method, we simply load the nib by name, register this nib with the UITableView, and then simply set the rowHeight of the UITableView to match the height of the first view in the nib which we already know is simply a UITableViewCell.

 

    UINib* nib = [UINibnibWithNibName:@"ADTableViewCell"bundle:nil];

    [self.tableViewregisterNib:nib forCellReuseIdentifier: [ADCustomCellIdentifier]];

    self.tableView.rowHeight = ((UITableViewCell*)[[nib instantiateWithOwner:selfoptions:nil] objectAtIndex:0]).bounds.size.height;

 

In the example code above, we additionally reference a predefined class method for the cell identifier we conveniently placed in the strongly typed class representing the UITableViewCell with [ADCustomCell Identifier].

Tags:   , , ,
Categories:   iPhone / iPad | Software
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed