Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS 5 UITableViewCell custom XIB's aka "Am I losing my mind?"

Alright. I've done more custom UITableViewCells than I can possibly count over the last three years.

Then comes iOS 5 and I just got a project on my desk where I have to do yet some more.

So the way I used to do this is I would make a custom XIB, drag a UITableViewCell onto the canvas, plug my controls in, set the custom class, do my linkage... then load instantiate the cell in code by looping through the objects after unpacking the XIB.

Did it so many times I had a single Category function to handle the whole thing.

Now all of a sudden in iOS 5 it's serving up big blank white table cells every time I make a custom cell.

Here are the following characteristics of the custom cells being inserted into the table

1) Show completely stark white apart from the "default" UITableViewCell controls (textLabel, etc, will populate and show when I set text to them).

2) isKindOfClass(MyCustomCellClass) reports true

3) Setter methods on custom cell class are functioning, object pointers for set values AND custom UILabels and such all report as non-nil, meaning the cell is actually getting made and properly being instantiated from the XIB

4) Will show offbeat controls like a UIStepper unconditionally for some reason. So yes, if I place a stepper in my custom cell, it shows, but labels and images don't.

As best I can figure, something is obscuring the content view by default, or otherwise the custom controls I am creating are no longer being appropriated to the contentView of the cell anymore (like they used to be), and are instead just being tossed into outer space.

For example, in iOS 4 XIB's, I used to see this when crafting a custom cell (Pulled from Apple's iOS 5 documentation):

Pulled from Apple's iOS 5 documentation

But as of this moment, this is what I see when doing the same in an iOS 5 XIB

enter image description here

So note that it's not explicitly showing that little Content View dotted line anymore.

I've really exhausted all of my diagnostic knowhow on this problem. I've tried manually pumping all the custom labels directly into the content view at runtime but even that doesn't work.

I'm looking for any ideas at all.

edit

Code for loading XIB

if (cell == nil)
{
    [[NSBundle mainBundle] loadNibNamed:@"XCCodeViewCell" owner:self options:nil];
    cell = codeCell;
    self.codeCell = nil;
}

This is currently what it is after simplifying it based on Apple's newer iOS 5 recommendations. The XIB has its owner properly set to the class of "self", and codeCell is linked to the cell properly, with the right class and identifier.

like image 633
M. Ryan Avatar asked Jan 24 '12 18:01

M. Ryan


1 Answers

Wow, This one took me a while to test but I think I've got the answer for you...

With Xcode4 in interface builder they added the ability to set up tableViewCells statically in interface builder. This is cool when you want to design tableViews that won't change and you don't want to write them in code. To facilitate this they have set the ability to set the tableViewCell style in IB and see what that looks like. When you design your own cell with your own subviews you select "Custom".

With the iOS 5 developments I found the following; When i loaded a cell from by xib and then programmatically set textLabel.text or another attribute of one of the standard cell styles it seems that the tableViewCell generates that standard view with the default labels in it and overlays your custom view with it. Thus to keep your custom cell subviews you need to not access any of the standard tableCell's properties.

Cool.

Also new in iOS 4 was UINib. You should use UINib for loading tableViewCells from xibs as it has caching and is tonnes faster (all the better for your tableView scrolling). The ARC code looks like this:

header:

@property (nonatomic, strong) UINib * tableCellLoader;

.m file:

-(void)viewDidLoad{
    [super viewDidLoad];
    self.tableCellLoader = [UINib nibWithNibName:@"MyTableViewCell" bundle:nil];
}

Then in tableView:cellForRowAtIndexPath:

...
if (cell == nil) {
    cell = [[self.tableCellLoader instantiateWithOwner:self options:nil] objectAtIndex:0];
}
...

EDIT: updating for new in iOS 5 New in iOS 5 is the ability for the UITableView to keep xibs for certain cell reuse identifiers and then instantiate a new cell of that certain type if there aren't any in the reuse queue.

Check out

– registerNib:forCellReuseIdentifier:

Then when you do

– dequeueReusableCellWithIdentifier:

You're guaranteed to get a UITableViewCell of the specified type back. It saves you doing the whole UINib thing yourself.

like image 184
jackslash Avatar answered Oct 11 '22 15:10

jackslash