Monday, May 10, 2010

UITableViewCell Reuse Cautions

Here’s a problem that perplexed me for quite some time today. I was making an options page for an iPhone app. I set up a UITableView with a few different sections. Each section contained different kinds of options such as dates, times, and switches. Due to the variations in options, some cells were set up differently from others. For the switches, I added a UISwitch as a subview to the content view of a cell. For dates and times, I was displaying the date or time as a detailed text label. Everything looked nice, that is until I scrolled. When scrolling, the cells had a mix of UISwitches and text labels mixed together. It was a mess. After several hours of reading documentation I uncovered the source of the problem. Ironically, it was something small and simple. When a cell scrolls off the screen it is reused as one of the cells scrolling onto the screen. Normally there are no problems with cell reuse because the cells of a table are usually uniform in use and layout. When a cell is recycled, all of the old values are usually overwritten by the new values. In my case, I wasn’t using all of the properties for all of the cells. This lead to the conflicts that left me bewildered for so long.

Removing the detailed text label was easy. All I need to do was set the it to an empty string. Removing the UISwitch wasn’t as easy. Fortunately, I found a piece of code on stackoverflow.com that helped me out. What I did was get all of the subviews from the cell’s content view and release them. It looks like this:

NSArray * subviews = [[NSArray alloc] initWithArray: cell.contentView.subviews];
        
for (UIView * subview in subviews)
        [subview removeFromSuperview];
        
[subviews release];

It was a small change but made all the difference. With those changes in place, my options page was flawless. I never cease to be amazed by all the bugs that result from simple mistakes.