The best way to do custom, reusable UITableViewCells

Posted by on Dec 27, 2011 in Developer | 1 comment

The best way to do custom, reusable UITableViewCells

So it’s probably the most common thing you want to do in iOS development, and that’s to create a page which shows a scrollable list of items, that is, a UITableView. UITableView, of course, comes with 4 default table cell styles, which can accommodate basic needs, but almost inevitably, you want to do something that isn’t covered by the default types. Perhaps you want to give it a nice gradient background, or maybe you would like to support multiline detail text, or maybe you’d like to have images loaded remotely, on a background thread, in order to maintain maximal scrolling performance. Maybe you need to add a UITextfield or a UISwitch. The variations are endless. As are the ways that you can implement a solution.

So rather than go through the different ways we can accomplish this task, let’s just cut to the chase and show a great solution which gives us completely custom, flexible cells, which can be reused in multiple view controllers. Yes, that means there is no need to specify a File’s Owner on your UITableViewCell subclass, and no outlets to hook up into your view controller.

Here’s the recipe. We’ll use a list of menu items from a restaurant for our example:

  1. Create a new subclass of UITableViewCell – let’s call it MenuItemCell.
  2. Create a new view – let’s call it MenuItemCell.xib
    1. In the editor, delete the UIView
    2. Drag in a UITableViewCell object
    3. Change the class of the UITableViewCell to MenuItemCell
    4. Create UI elements, such as UILabels, UIImageViews, etc in your MenuItemCell.xib
    5. Show your assistant editor (Opt-Cmd-Return), such that you have MenuItemCell.xib on the left, and MenuItemCell.h on the right
    6. Control-drag from any UIControls that you have created in MenuItemCell.xib to MenuItemCell.h, to create outlets.
    7. Give the UITableViewCell a unique Reuse Identifier (eg. MenuItemCell)
  3. Your UITableViewCell subclass is now done. It can be re-used anywhere you like, without hooking it up to UIViewControllers using further outlets.
  4. To actually use your fancy MenuItemCell in a UIViewController, implement UITableViewDataSource:
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        static NSString *cellIdentifier = @"MenuItemCell";
        MenuItemCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
        if (cell == nil) {
            // Load the nib and assign an owner
            NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:cellIdentifier owner:self options:nil];
            cell = [topLevelObjects objectAtIndex:0];
        }
     
        MenuItem *menuItem = [menuItems_ objectAtIndex:[indexPath row]];
     
        cell.lblTitle.text = [menuItem.name capitalizedString];
        cell.lblDetails.text = menuItem.summary;
        cell.photo.image = [UIImage imageNamed:menuItem.photo];
     
        return cell;
    }
  5. If you would like to customize your xib even more, implement its awakeFromNib method (ie. in MenuItemCell.m):
    - (void) awakeFromNib
    {
        // set the gradient view
        MBGradientView *backgroundGradientView = [[MBGradientView alloc] initWithFrame:self.contentView.frame];
        backgroundGradientView.color1 = [UIColor whiteColor];
        backgroundGradientView.color2 = [UIColor colorWithHexString:@"F3F3F3"];
        backgroundGradientView.gradientStartPoint = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
        backgroundGradientView.gradientEndPoint = [NSValue valueWithCGPoint:CGPointMake(0, 0.5)];
        self.backgroundView = backgroundGradientView;
        [backgroundGradientView release];
     
        // pretty up the image
        self.photo.layer.cornerRadius = 5.0;
        self.photo.layer.masksToBounds = YES;
        self.photo.layer.borderColor = [UIColor lightGrayColor].CGColor;
        self.photo.layer.borderWidth = 1.0;
    }

And that’s it! For Bonus Points, you can put multiple (presumably related) custom cells in the same nib, and load them up from anywhere.

One last thing – make sure you return the proper height for your new custom cell when implementing -(void)tableView:heightForRowAtIndexPath:

One Comment

Join the conversation and post a comment.

Leave a Comment

Your email address will not be published.


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">