6

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?

Bryant Harris
  • 728
  • 5
  • 21

3 Answers3

4

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.

buckleyJohnson
  • 459
  • 4
  • 12
2

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).

gagarwal
  • 4,224
  • 2
  • 20
  • 27
  • It's hooked up correctly with it's FileOwner. The error is saying that it cannot find statusLabel on NSObject (or on MYViewController if I pass that controller as self in as the owner in the loadNibNamed:owner: – Bryant Harris Jan 08 '14 at 18:34
  • 1
    For loading Views from NIB connecting to FileOwner do not work, unless view are part of UIViewController hierarchy. You need to connect the outlets of UITableViewCell in NIB file to labels. For doing this right click on UITableViewCell in your NIB (you can find it in left pane below the FileOwner) and connect outlets. – gagarwal Jan 09 '14 at 19:39
  • 1
    right but the proper connection is to your custom class, not the FileOwner. When you drag the referencing outlet drop it on the custom class in the hierarchy. The problem is IB lets you drag it to FileOwner and there exists the IBOutlet as you expect, but it doesn't work. Dropping on the custom class displays the same outlets but there it works. – John May 22 '14 at 17:46
0

Also Check If MyCell.xib file is not (mistakenly!) get added inside

Target Settings -> Build Phases -> Compile Sources

Compile Sources are For All .m Files and Not for .Xib resource files.

And

Copy Bundle Resources are for .Xib resource files.

Vinod Supnekar
  • 143
  • 1
  • 7