Save my hair, please or point out my (obvious) error. I am trying to use a UITableViewStyle of UITableViewCellStyleSubtitle in a subclassed UITableViewController.
I define a static constant in the implementation:
static NSString * const kAHCellIdentifier;
In viewDidLoad I register a tableView class:
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:kAHCellIdentifier];
Then in tableView:cellForRowAtIndexPath I initialise the the cell as follows:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kAHCellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kAHCellIdentifier];
}
When running the app (device or sim) the cells load but the detailTextLabel doesn't show, however if I initialise like this, it works correctly*
My guess is that the constant is not actually static, or that there is a bug (8.0.2), or there is something that I am missing completely due to lack of sleep or whatever.
It can also be noted, that if I don't register the class there is a compiler error (expected) but no error even though the cell identifiers are different (which I guess is expected as I could register different classes for different cell styles.
What am I missing?
Edit
Using [tableView dequeueReusableCellWithIdentifier:kAHCellIdentifier forIndexPath:indexPath]; has no effect either.
Shorter question
Why does the dequeueReusableCellWithIdentifier return nil and thus initiate the cell using the UITableViewCellStyle in the cell == nil block if I use a static NSString in the cellForRowAtIndexPath method call, and not, if I use a class level global constant as defined above.
Additional
Some more testing has yielded some different results. If you register a class for the cell reuse identifier and then give the cell a different identifier in cellForRowAtIndexPath then it works. If you give it the same name as the registered class, then it doesn't work as expected.
Answer
After some testing, and @MANIAK_dobrii's answer, some clarity.
If you want to use the newer cell dequeue method dequeueReusableCellWithIdentifier:forIndexPath and need to use a UITableViewCellStyle other than default, you'll need to subclass UITableViewCell and override the tableview style in the initWithStyle method call.
If you are happy to use the older method then make sure you don't register a class for the reuse identifier otherwise it will not work.
That's interesting, because I've just found a new paragraph in the docs for dequeueReusableCellWithIdentifier: I didn't see last time I was looking there:
If you registered a class for the specified identifier and a new cell must be created, this method initializes the cell by calling its initWithStyle:reuseIdentifier: method. For nib-based cells, this method loads the cell object from the provided nib file. If an existing cell was available for reuse, this method calls the cell’s prepareForReuse method instead.
Does this mean that if you register a class even dequeueReusableCellWithIdentifier: will try to create cell if it is not available in the reuse queue and always return a valid cell? Since -dequeueReusableCellWithIdentifier:forIndexPath: got available, I was using only it. So, my guess is that your
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
never get's called and you end up with cells created via
[[registred_class alloc] initWithStyle:STANDARD_STYLE reuseIdentifier:registred_reuse_identifier];
At the same time, you've stated, that you get compile time errors if you don't register class, that's strange, you should not get any.
So, my solution would be or:
1. Don't register cell class via -registerClass:forCellReuseIdentifier: and use -dequeueReusableCellWithIdentifier: to get reused cells or create them as you're doing it right now. Again, use oldschool approach, you don't register anything, just dequeue if there is and create if there is no.
// I've put it here just for a clarification that that's doesn't matter for the case
static NSString *const cellID = @"CellID";
// Just this, do not register anything, cell should get the same id as you ask
// i.e. you should init cell with the same id you then try to dequeue
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if(!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID];
}
cell.textLabel.text = @"Title";
cell.detailTextLabel.text = @"subtitle";
return cell;
}
or:
2. Create nib, put a UITableViewCell there, make it's style be UITableViewCellStyleSubtitle and register that nib for a reuse identifier instead of a class with registerNib:forCellReuseIdentifier:.
Also, make sure, you set all the titles/colors/transparencies right, so that you don't just set empty string or nil to a label on a cell.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With