iphoneuitableviewuinib

Assigning the outlet for a UITableViewCell using UINib


I looked at the TableViewUpdates/TVAnimationGestures from Apple's WWDC 2010 code and am having trouble duplicating a UITableViewCell subclass. This is what I've done:

I created a new UITableViewCell subclass with some simple properties:

@interface TargetDetailTableViewCell : UITableViewCell

@property (nonatomic, retain) IBOutlet UILabel *DescriptionLabel;
@property (nonatomic, retain) IBOutlet UILabel *ValueLabel;
@property (nonatomic, retain) IBOutlet UIImageView *DotImageView;

In the .m, I just release memory. In IB, I change my class to TargetDetailTableViewCell for the UITableViewCell I just dragged into IB. I connect the outlets from the TargetDetailTableViewCell to the appropriate labels and image view.

In the class I want to use this:

@class TargetDetailTableViewCell;

//some properties
@property (nonatomic, assign) IBOutlet TargetDetailTableViewCell *TargetCell;

In the .m:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {    
    static NSString *TargetCellIdentifier = @"TargetDetailTableViewCellIdentifier";
    TargetDetailTableViewCell *cell = (TargetDetailTableViewCell *)[tableView dequeueReusableCellWithIdentifier:TargetCellIdentifier];

    if (cell == nil) {
        UINib *nib = [UINib nibWithNibName:@"TargetDetailTableViewCell" bundle:nil];
        [nib instantiateWithOwner:self options:nil];
        cell = self.TargetCell;
        self.TargetCell = nil;
    }
// set some labels
return cell;
}

When I run it, I get the error: Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'

The only think I can see that is different between Apple's example and mine is that when I ctlr-click on the subclass of UITableViewCell in their IB, they have a File's Owner property set. I have no idea how they connected that outlet as it is declared as a property in the class they use the cell, but there is no physical IB connection they make. Can someone explain that to me or what I am doing wrong?

Also, if anyone can explain this, that would be great:

        UINib *nib = [UINib nibWithNibName:@"TargetDetailTableViewCell" bundle:nil];
        [nib instantiateWithOwner:self options:nil];
        cell = self.TargetCell;
        self.TargetCell = nil;

It seems like you create the nib and the owner of the nib that gets instantiated from memory is the class you are in or self (my viewcontroller). Then the last two lines confuse me. It's like you tell your cell to point to the newly created object, then you set the newly created object to nil. Which in my head I think, the cell now points to nil as well. Thanks.


Solution

  • You need to have an owner in your custom table view cell nib and that owner needs to be your TableViewDataSource class (i.e. the table view controller which implements the cellForRowAtIndexPath method and has the TargetCell outlet to the table cell).

    You also need to connect this TargetCell outlet from the file owner (the TableViewController) to your custom table view.

    The reason for this is that when you load the nib, with your table view controller as the owner, it will then set the outlet that you have (the TargetCell property) to point to the table view cell defined in your nib.

    You then copy this reference to the cell method variable, configure it and return it. You assign the property to nil after copying it because you only needed it as a bootstrap to get a reference to the object in the nib for use in the cellForRowAtIndexPath method.