Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITableViewCell dequeueReusableCellWithIdentifier with custom initializer

I'm using [UITableView registerClass: forReuseIdentifier:] and [UITableView dequeueReusableCellWithIdentifier:] in order to queue and dequeue UITableViewCells.

For example, in viewDidLoad:

[self.storeTableView registerClass:[StoreLineGraphCell class] forCellReuseIdentifier:@"StoreLineGraphCellIdentifier"];

And in cellForRowAtIndexPath:

StoreLineGraphCell *cell = (StoreLineGraphCell*)[self.storeTableView dequeueReusableCellWithIdentifier:@"StoreLineGraphCellIdentifier"];

In doing this, the initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier initializer is called for the UITableViewCell. The problem is that I need to use a custom initializer in order to create the cell with necessary options. For example, the ability to do something like this:

StoreLineGraphCell *cell = [[StoreLineGraphCell alloc] initWithReuseIdentifier:@"StoreLineGraphCell" isLocked:YES isUpcoming:YES];

This doesn't seem possible with the registerClass & dequeue pattern. I'd like to keep it in an initializer as it should only be run once, not every time the cell is dequeued. Is there a proper way to accomplish this?

like image 209
Whoa Avatar asked Mar 24 '14 14:03

Whoa


3 Answers

While you follow the usual pattern for cell re-usage (as you do with register class & dequeue), I do not see an easy to implement way of doing that.

If I were you I would create an additional initialization method (not following the usual init pattern of obj-c) or simply setters and call that following the dequeueReusableCellWithIdentifier call.

StoreLineGraphCell *cell = (StoreLineGraphCell*)[self.storeTableView dequeueReusableCellWithIdentifier:@"StoreLineGraphCellIdentifier"];
[cell furtherInitWithLocked:YES andUpcoming:NO]; // ... or so
like image 90
Hermann Klecker Avatar answered Sep 16 '22 15:09

Hermann Klecker


You are using the correct registerClass and dequeue methods but for invoking/setting your custom properties you should configure creating a separate method and invoke it.

Instead of this:

StoreLineGraphCell *cell = [[StoreLineGraphCell alloc] 
initWithReuseIdentifier:@"StoreLineGraphCell" isLocked:YES isUpcoming:YES];

You can do this:

StoreLineGraphCell *cell = // get the dequeue cell 
[cell configure]; 

Inside the configure method you can set the properties as shown below:

-(void) configure 
{
   self.isLocked = YES; 
   self.isUpcoming = YES; 
}
like image 39
azamsharp Avatar answered Sep 18 '22 15:09

azamsharp


It is a common problem which I encounter today.
However, it can be solved like this.
Because the cell class registered before dequeueReusableCellWithIdentifier method called, after executed
cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier],
the cell always be not nil and return by
- initWithStyle:style reuseIdentifier:reuseIdentifier.
It seems like that you can not customize your own init method.
But, if you do not register cell class before, then dequeueReusableCellWithIdentifier will return nil if the tableview has no reusable cells.
So, we should check cell value returned by dequeueReusableCellWithIdentifier, if it is nil, then we can init it with our custom method.

cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier]
if (!cell) {
    cell = /* custom init method */
}

That's done! If we want to customize subclass cell init method, so do not register cell class before.

like image 39
Qinghua Avatar answered Sep 18 '22 15:09

Qinghua