Table view and size-adapting cells

Table views are one of the most commonly used UI components in iOS apps. They usually display text with varying lengths.

Prior to iOS7, developers had to calculate the height of each cell to accommodate to its content, and provide it in the table view delegate method -tableView:heightForRowAtIndexPath:. Now the cells self-sizing behavior can be achieved a lot more easily, with very few lines of code.

This article is a step-by-step guide to implement the dynamic cell heigh. It makes use of storyboards and several object properties that provide the layout system with the baseline for automatically calculating and applying the correct cell height.

Create a basic table view

Start by creating a single view application project, open the storyboard and remove the default view controller, which is not useful for what we want to build. Also remove the ViewController class from the Project navigator; we will replace it with UITableViewController subclass which conforms to the UITableViewDelegate and UITableViewDataSource protocols and saves us from writing the code that deals with the communication between the model and the view.

Drag a table view controller from the Object library to the storyboard and make sure the “Is initial view controller” checkbox is checked. This view controller becomes the entry point and app delegate will load it first when the app is launched.

initial view controller

Create a new class and make it inherit from UITableViewController. I call this class DynamicTableViewController :

custom class table view controller

Remove the commented code which comes with the UITableViewController class template, we will not need it. I generally recommend removing most of the suggested code imported from the templates, except maybe the initializers, which are usually overridden, and a few mandatory protocol methods like the two uncommented UITableViewDataSource methods in our custom class. This declutters the code file and the deleted methods can easily be added later, if needed.

Next, link together the table view controller from the storyboard to the custom class. This is done by initializing the Class attribute in the Identity inspector:

link custom class to storyboard table view controller

In the storyboard, select the prototype cell from the table view and give it a reuse identifier in the Attributes inspector:

cell reuse identifier

If you run the app right now, you only will see an empty table. It’s time to add some content to our table view. In the sample project you can download here, I’ve used an array to store a few strings of various lengths and used these strings to populate the table view cells.

You’ve probably noticed the warnings generated in the DynamicTableViewController by the class code template. They are part of the data source delegate methods, some of which we have to implement if we want the strings to be displayed in the table view:

Make the cells self-sizing

If we run the application again, we note that the table rows are filled with the text we provided in the data source, but the text is truncated at its tail and the cells are the same height. By default, the table view cells don’t adjust their size to fit the text content. We have to initialize two properties of the table view to enable the auto-resizing:

  • estimatedRowHeight: indicates a rough estimation of the height used by the layout engine as the default value for all the table view cells it create in memory. The value you provide is arbitrary. The real height is calculated on the fly for each cell that is about to be displayed. Assigning a default height improves the overall performance of the cell loading process.
  • rowHeight: should be initialized to UITableViewAutomaticDimension, except for iOS8 where it’s the default value.

The values for these table view properties can be set in the -viewDidLoad method of our view controller:

We also have to enable multi-line display for the labels in each cell and that’s something we can do by setting the numberOfLines cell property to 0 in the -tableView:cellforRowAtIndexPath delegate method.

Run the application and you will see the table view cells have adjusted their height depending on the length of the text they display. Or not… When the table view is displayed for the first time, the dynamic height of the visible cells doesn’t seem to be calculated. The workaround is to force the data reload on -viewDidAppear: by calling the -reloadData method on the table view, as the guys from UseYourLoaf explain here.

After you force the data reload on first display, things should work as expected:

working self-sizing cells

Bonus

By doing everything we did until now, we also get dynamic type support for free, because the text is displayed using the system font. If we were using a custom font, we would have to define the preferred font size for each text style used in the app. But that’s a topic for another blog post.

If you enable the Larger text option in the device Preferences app / General / Accessibility, and change the font size, then run the table view app again, you will note the font size has changed automatically to match the global setting.

dynamic type with self-sizing tableview cells

Conclusion

As demonstrated in this article, resizable table view cells are really easy to implement, although there are a few gotchas along the way we should look out for.

 

Catalin Rosioru

 

One thought on “Table view and size-adapting cells

Comments are closed.