Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I recycle UITableViewCell objects created from a XIB?

I'd like to create custom UITableViewCell using an XIB, but I'm not sure how to recycle it using UITableViewController's queueing mechanism. How can I accomplish this?

Folks, this question was intended to be self answered as per the FAQ, although I love the awesome responses. Have some upvotes, treat yourself to a beer. I asked this because a friend asked me and I wanted to put it up on StackOverflow. If you have anything to contribute, by all means!

like image 273
Moshe Avatar asked Feb 05 '12 15:02

Moshe


People also ask

How to add UITableViewCell in xib?

h, a new subclass of UITableViewCell and add IBOutlets for the components you want. Then create a new "Empty XIB" file. Open the Xib file in IB, add a UITableViewCell object, set its identifier to "MyCellIdentifier", and set its class to MyCell and add your components. Finally, connect the IBOutlets to the components.

What is prototype cell?

A prototype cell acts a template for your cell's appearance. It includes the views you want to display and their arrangement within the content area of the cell. At runtime, the table's data source object creates actual cells from the prototypes and configures them with your app's data.


4 Answers

If you're using iOS 5 you can use

[self.tableView registerNib:[UINib nibWithNibName:@"nibname" 
                                           bundle:nil] 
     forCellReuseIdentifier:@"cellIdentifier"];

Then whenever you call:

cell = [tableView dequeueReusableCellWithIdentifier:@"cellIdentifier"];

the tableview will either load the nib and give you a cell, or dequeue a cell for you!

The nib need only be a nib with a single tableviewcell defined inside of it!

like image 121
Tony Million Avatar answered Oct 22 '22 12:10

Tony Million


Create an empty nib and add the table cell as the first item. In the inspector, you can add the reuseIdentifier string in Interface Builder.

To use the cell in your code, do this:

- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *reuseIdentifier = @"blah"; //should match what you've set in Interface Builder
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
    if (cell == nil)
    {
        cell = [[[NSBundle mainBundle] loadNibNamed:@"YourTableCellNib" owner:nil options:nil] objectAtIndex:0];
    }

    //set up cell

    return cell;
}

There is another method where you create an outlet for your cell and load the cell nib using the controller as the file's owner, but honestly this is much easier.

If you want to be able to access the subviews you've added to the cell in the nib, give them unique tags and access them with [cell viewWithTag:x];

If you want to be able to set custom properties on the cell, you'll need to create a custom UITableViewCell subclass, then just set that as the class of your nib in InterfaceBuilder and cast the UITableViewCell to your custom subclass when you dequeue it in the code above.

like image 2
Nick Lockwood Avatar answered Oct 22 '22 12:10

Nick Lockwood


To set up a custom UITableViewCell using a XIB, you have to do several things:

  • Set up an IBOutlet in your header
  • Configure the table view cell in Interface Builder
  • Load the XIB inside of tableView:cellForRowAtIndexPath:
  • Configure it like any other cell

So... Let's set up an IBOutlet in the header file.

@property (nonatomic, retain) IBOutlet UITableViewCell *dvarTorahCell;

Don't forget to synthesize it inside the implementation file.

@synthesize dvarTorahCell;

Now, let's create and configure the cell. You want to pay attention to the Cell Identifier and the IBOutlet as shown below:

enter image description here

Now in code, you load up the XIB into your cell as shown here:

enter image description here

Notice that the Cell Identifier in Interface Builder matches the one shown in the code below.

Then you go ahead and configure your cell like any other.

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {

    [[NSBundle mainBundle] loadNibNamed:@"YUOnlineCell" owner:self options:nil];
    cell = dvarTorahCell;
    dvarTorahCell = nil;
}

//configure your cell here.

Just note that when accessing subviews, such as labels, you now need to refer to them by tag, instead of by property names, such as textLabel and detailTextLabel.

like image 2
Moshe Avatar answered Oct 22 '22 12:10

Moshe


Here how you can do:

- (UITableViewCell *)tableView:(UITableView *)tableView 
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  YourCustomeCell *cell = (YourCustomeCell *)[tableView dequeueReusableCellWithIdentifier:CellClassName];
  if (!cell)
  {
    NSArray *topLevelItems = [cellLoader instantiateWithOwner:self options:nil];
    cell = [topLevelItems objectAtIndex:0];
  }

  return cell;
}

Where cellLoader in .h is defined as follow:

UINib *cellLoader;

and in .m is istantiated as follows (for example during initialization):

cellLoader = [[UINib nibWithNibName:CellClassName bundle:[NSBundle mainBundle]] retain];

and CellClassName is the defined in .m as follows (is also the name for your xib).

static NSString *CellClassName = @"YourCustomeCell";

Do not forget to use the string CellClassName also in your xib created cell.

For further info I suggest you to read this fantastic tutorial creating-a-custom-uitableviewcell-in-ios-4.

Hope it helps.

P.S. I suggest you to use UINib because is an optimized method to load xib files.

like image 1
Lorenzo B Avatar answered Oct 22 '22 13:10

Lorenzo B