Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loading UITableViewCell from a xib (this class is not key value coding-compliant for the key)

I'm curious as to the proper way to use a xib file to layout the contents of a UITableViewCell. When I try to follow all the steps I find on the Internet I always get

Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSObject 0x10fe7d790> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key statusLabel.'

So here's the related code

@interface MyCell : UITableViewCell

@property (nonatomic,strong) IBOutlet UILabel* messageLabel;
@property (nonatomic,strong) IBOutlet UILabel* statusLabel;

And in my UIViewController I've tried both

-(void)viewDidLoad {
     [self.tableView registerNib:[UINib nibWithNibName:@"MyCell"
                                           bundle:[NSBundle mainBundle]]
     forCellReuseIdentifier:@"CustomCellReuseID"];
}

or using

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"CustomCellReuseID";
    MyCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if ( !cell ) {
        cell = [[[NSBundle mainBundle] loadNibNamed:@"MyCell" owner:self options:nil] 
lastObject];
        // or sometimes owner is nil e.g.
        //cell = [[[NSBundle mainBundle] loadNibNamed:@"MyCell" owner:nil options:nil] 
lastObject];
    }

    // ... remainder of cell setup

    return cell;
}

Both of these approaches fail with the exception I mentioned in the title. It appears that with owner:self the error is because the UIViewController doesn't have the IBOutlet properties. With owner:nil it's because it internally uses an NSObject which of course also doesn't have the IBOutlet properties.

The only work around I've found is as follows. Within the init method for my cell I add the returned view/cell to my initializing cell

e.g.

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // nil out properties

        [self.contentView addSubview:[[[NSBundle mainBundle] loadNibNamed:@"MyCell" owner:self options:nil] lastObject]];
    }
    return self;
}

This seems really hokey (although I can also just change the base type in the xib to UIView instead of MyCell or UITableViewCell) which makes it feel slightly less hokey.

I've seen a lot of posts where people run into this particular error. This is usually explained away as being a wiring problem in the xib itself, however if I remove all connections in the xib it loads fine, but the moment I add back a connection between a ui element and the file owner the error returns, so I don't think it has anything to do with 'cleaning up' the xib (even looking at the XML for the xib there's no errant connections listed).

Does anyone else have any thoughts as to how this error comes about?

like image 333
Bryant Harris Avatar asked Jan 03 '14 22:01

Bryant Harris


2 Answers

I had to make sure that when creating the outlet to specify that I was hooking to the cell, not the object's owner. When you drag your connection from the label in your cell to the class, the menu appears so you can name it and you have to select it in the 'object' dropdown menu (you can choose 'files owner' or the cell's class name, choose the cell's class name). Of course you must declare the cell's class as this class too, not just 'TableViewCell'. Otherwise I would keep getting the class not key compliant. So now I have both the cell and the files owner named of that class.

like image 186
buckleyJohnson Avatar answered Oct 21 '22 16:10

buckleyJohnson


Have you connected the outlets for "messageLabel and statusLabel" in the Cell Nib file? The error states that the IBOutlet property for "statusLabel" is not found in the Nib file (connection issue).

like image 2
gagarwal Avatar answered Oct 21 '22 15:10

gagarwal