Using iPhone - dequeueReusableCellWithIdentifier

I am working on an iPhone application that has a fairly large UITableView with data taken from the Internet, so I am trying to optimize its creation and use.

I found out that dequeueReusableCellWithIdentifier is very useful, but after looking at many source codes using this, I am wondering if the use I use for this function is good.

Here's what people usually do:

UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"Cell"]; // Add elements to the cell return cell; 

And here is how I did it:

 // The cell row NSString identifier = [NSString stringWithFormat:@"Cell %d", indexPath.row]; UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:identifier]; if (cell != nil) return cell; cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:identifier]; // Add elements to the cell return cell; 

The difference is that people use the same identifier for each cell, so excluding one of them avoids adding a new one.

For me, the task of the queue was to provide each cell with a unique identifier, therefore, when the application asks that the cell is already displayed, neither selection nor addition of elements is required.

In thin, I donโ€™t know which is better, the โ€œgeneralโ€ method allows you to use the table memory for the exact number of cells that it displays, but the method I use, apparently, it stores all the calculated cells, but can cause a large amount of memory ( if there is no internal limit for the queue).

Am I using it this way? Or does it depend only on the developers, depending on his needs?

+60
optimization objective-c iphone uitableview
May 28 '10 at 12:21
source share
6 answers

The purpose of dequeueReusableCellWithIdentifier is to use less memory. If the screen can correspond to 4 or 5 cells of the table, then when reused, you will only need 4 or 5 cells of the table allocated in memory, even if the table has 1000 entries.

In the second case, reuse does not exist. In the second case, there is no advantage, since you are using an array of table cells. If your table has 1000 records, then you will have 1000 cells allocated in memory. If you are going to do this, you will put them in an array and just index the array with the row number and return the cell. For small tables with fixed cells, which can be a smart solution, for dynamic or large tables this is not a good idea.

+70
May 28 '10 at 12:55
source share

Like for cell id. Instead of just using a "cell" for an identifier, and instead of using a unique identifier such as an OP, could you use a "type identifier"? For example, if there were 3 types of cells in my table - one with a very complex subarray, one with just Style1 , and one with Style2 , I had to identify these three all separately, and then just rebuild them if dequeue up nil happens.

For example:

 -(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath{ NSString* ident = @""; if(indexPath.section == 0) ident= @"complicated"; if(indexPath.section == 1) ident= @"style1"; if(indexPath.section == 2) ident = @"style2"; UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:ident]; if(cell == nil){ if(ident == @"complicated"){ cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:ident] autorelease]; // do excessive subview building } if(ident == @"style1"){ cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyle1 reuseIdentifier:ident] autorelease]; } if(ident == @"style2"){ cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyle2 reuseIdentifier:ident] autorelease]; } } if(ident == @"complicated"){ // change the text/etc (unique values) of our many subviews } if(ident == @"style1"){ [[cell textLabel] setText:@"Whatever"]; } if(ident == @"style2"){ [[cell textLabel] setText:@"Whateverelse"]; } return cell; } 

(This code probably wonโ€™t run because I wrote it here, but hopefully you get this idea.)

I donโ€™t think that Apple would have created the idea of โ€‹โ€‹reusing cells with identifiers if they wanted all identifiers to be "cell" , right?

+20
Jun 09 '10 at 17:46
source share

The documentation that helped me understand why the idiomatic way (the one you described first) works best, a reference to the UITableViewCell class on initWithStyle:reuseIdentifier:

The reuseIdentifier says:

You must use the same reuse identifier for all cells of the same form.

And the discussion section reads:

The reuse identifier is associated with these cells (rows) of the table view, which have the same general configuration, minus the contents of the cell.

These statements make me understand that the idiomatic way to use dequeueReusableCellWithIdentifier inside your implementation of tableView:cellForRowAtIndexPath: for your UITableViewDataSource creates one cell object for each visible row, regardless of the total number of rows available.

+13
Aug 02 '11 at 1:13
source share

I think the first one is the best (and, as you said, generic) way to implement a UITableView . From your second path, memory will be allocated for each new cell to be displayed, and memory will not be reused.

+4
May 28 '10 at 12:27
source share

UITableView internally uses a cell with an identifier as a "template". So the next time you (read as a table) try deque, it just creates a new cell, but uses the stored object as a template. Therefore, you still have to update your user interface to display the contents of the cell in accordance with the context.

It also means that UITableView does the memory management for us on its own. Theoretically, there will only be as many UITableViewCell objects as there are visible cells. But in practice, there may be a couple more pending memory release.

This basically saves a lot of time, esp memory in scenarios where you have 1000 cells.

On any portable device where the memory is at a high level, we must postpone the allocation of any memory until the last moment and free it at the time of its execution. dequeAndReusing cell achieves this and does it pretty well.

On the other hand, if your cell is a customized cell, then we are likely to download it and extract it from it. If so, you can use the identifier for deque OR, you can download it from nib. There is no difference in the procedure.

The only difference may be in load time. Enabling table views to create a new cell using an identifier cell as a template may be slightly faster than loading from nib, but this is barely noticeable and depends on the context.

+1
Oct. 14 2018-11-11T00:
source share

To distinguish a cell from other cells, you can use the tag property for the cell, or if you use a custom cell, then it is very easy to enter any new property into the custom cell when you subclass UITableViewCell .

Even if after that you are stuck and still need to get a cell, you can try the following code

UITableViewCell *cell = [self cellForRowAtIndexPath:indexPath]

whereas it should be avoided to the extent that it creates a copy of the cell but does not return the existing cell, while the contents will have the same values.

0
Jul 12 2018-12-12T00:
source share



All Articles