abbood
abbood

Reputation: 23558

Why is UITableViewCell initialization not working inside initWithCoder

I'm trying to clean up my code and use MVC principles by pushing as much view related stuff as i can into the storyboard as well as custom UIView classes (ie as opposed to doing view related stuff on the UIViewController itself)

So I have a custom UITableViewCell (called CustomCell) that has several properties, one of them is my own label. Since I'm loading the cell from the storyboard, I initialize it with initWithCoder rather than initWithStyle:reuseIdentifier:, this is what I have in CustomCell.m which is a subclass of UITableViewCell (for some reason i couldn't figure out how to set a custom font using storyboard.. but that's beside the point of this question):

// CustomCell.m - subclass of UITableViewCell
- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        NSLog(@"customizing cell font having text %@", self.label.text);
        UIFont *customFont = [UIFont fontWithName:@"Montserrat" size:16];
        self.label.textColor = [UIColor redColor];
        [self.label setFont:customFont];
    }
    return self;
}

This simply doesn't work.. the log statement outputs null for the text simply b/c the text hasn't been loaded yet. self.label is also null (I don't know why I thought it should have been inflated from the nib by now) but even if I initialize it here.. it still won't work.

So my work around was to simply put this cell customization part here in the TableViewController:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell 
forRowAtIndexPath:(NSIndexPath *)indexPath {        
    UIFont *customFont = [UIFont fontWithName:@"Montserrat" size:16];
    [((CustomCell *)cell).label setFont:customFont];
}

and it worked just fine.. I'm unhappy with this method and I would like to know how to make it work from within CustomCell.m

update: to make things even more interesting.. if i put customization code for UITableViewCell properties inside initWithCoder, they work! consider this example:

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        UIView *bgColorView = [[UIView alloc] init];
        [bgColorView setBackgroundColor:[UIColor blueColor]];
        [self setSelectedBackgroundView:bgColorView];  // actually works!
    }
    return self;
}

which makes this even more weird.

Upvotes: 4

Views: 2471

Answers (2)

abbood
abbood

Reputation: 23558

Inspired by andykkt's comment, I found the explanation in awakeFromNib documentation:

The nib-loading infrastructure sends an awakeFromNib message to each object recreated from a nib archive, but only after all the objects in the archive have been loaded and initialized. When an object receives an awakeFromNib message, it is guaranteed to have all its outlet and action connections already established.

so that explains the weird behaviour above: initWithCoder instantiates a standard UITableViewCell (that already comes pre-baked with a backgroundView etc etc).. however it still doesn't recognize the outlets I've added to it via storyboard.. awakeFromNib does.

Upvotes: 7

Fahri Azimov
Fahri Azimov

Reputation: 11770

I suspect that initWithCoder: method doesn't draw the contents of the cell, it just, initialises the object, and as you have noticed, accessing any of the ui drawing methods of the cell actually 'draws' the cell to apply the changes you have made to the cell. You can see the same behaviour when initing UIViewController's using initWithNibName:bundle: method.

Upvotes: 0

Related Questions