TableView: dequeueReusableCellWithIdentifier "global" constant issues

Save my hair, please point out my (obvious) mistake. I am trying to use UITableViewStyle UITableViewCellStyleSubtitle

in a subclass of UITableViewController.

I define a static constant in the implementation:

static NSString * const kAHCellIdentifier;

      

In viewDidLoad

I am registering the tableView class:

[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:kAHCellIdentifier];

      

Then in tableView:cellForRowAtIndexPath

I initialize the cell like this:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kAHCellIdentifier];
if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kAHCellIdentifier];
}

      

When launching the app (device or sim) the cells are loaded but the detailTextLabel is not shown, however if I initialize this it works correctly *

I am assuming that the constant is not actually static, or that there is a bug (8.0.2), or that there is something that I am completely missing due to lack of sleep or whatever.

It can also be noted that if I do not register the class, a compiler error (expected) is thrown, but there is no error even if the cell ids are different (which I assume is expected since I could register different classes for different cell styles.

What am I missing?

Edit

The use [tableView dequeueReusableCellWithIdentifier:kAHCellIdentifier forIndexPath:indexPath];

also has no effect.

Shorter question

Why dequeueReusableCellWithIdentifier

does it return nil and thus initiate the cell with the UITableViewCellStyle in the block cell == nil

if I use a static NSString in the method call cellForRowAtIndexPath

, not if I use a class level global constant as defined above.

Additional

Several other tests gave slightly different results. If you register a class for a cell reuse id and then give the cell a different id in cellForRowAtIndexPath

then it works. If you give it the same name as the registered class, then it does not work as expected.

Answer

After some testing and @MANIAK_dobrii's answer, clarity.

If you want to use the dequeue method of a new class dequeueReusableCellWithIdentifier:forIndexPath

and you need to use something UITableViewCellStyle

other than the default, you need to subclass UITableViewCell

and override the tableview style in the method call initWithStyle

.

If you're happy with an older method, make sure you don't register the class for a reuse identifier, or it won't work.

+3


source to share


1 answer


This is interesting because I just found a new paragraph in the docs for dequeueReusableCellWithIdentifier:

I didn't see the last time I looked there:

If you have registered a class for the specified ID and a new cell needs to be created, this method will initialize 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 cells prepareForReuse.

Does this mean that if you register a class, it dequeueReusableCellWithIdentifier:

will even try to create a cell if it is not available in the reuse queue and always returns a valid cell? Since it -dequeueReusableCellWithIdentifier:forIndexPath:

became available, I only used it. So, I assume that your

if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}

      

are never called and you get cells created with

[[registred_class alloc] initWithStyle:STANDARD_STYLE reuseIdentifier:registred_reuse_identifier];

      



At the same time you stated that you get compile time if you don't register the class, which is weird, you shouldn't get it.

So my solution would be either:
1. Don't register the cell class with -registerClass:forCellReuseIdentifier:

and use -dequeueReusableCellWithIdentifier:

to get reusable cells or create them as you are doing right now. Again, use the oldschool approach, you don't register anything, just delete if you have and create if it doesn't.

// I've put it here just for a clarification that that 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 a nib, put a UITableViewCell in there, create a style UITableViewCellStyleSubtitle

and register this nib for a reuse id instead of a c class registerNib:forCellReuseIdentifier:

.

Also, make sure you set all headers / colors / transparencies correctly, so that you don't just set a blank line or nil to a label in a cell.

+3


source







All Articles