简体   繁体   中英

Reusing UITableViewCells with custom heights properly

From my understanding the main benefit of dequeuing reusable cells within UITableViewControllers is the saving of memory by only holding currently visible cells and their content in memory.

That said, it seems to make sense to create the content of a cell every time the cell is requested within cellForRowAtIndexPath (respectively GetCell() in MonoTouch) and to release the entire cell when not used/visible anymore.

That works if all cells have the same height. But if only one cell has another dynamic height, which is calculated by creating the content view, the height must be set within heightForRowAtIndexPath (respectively GetHeightForRow() in MonoTouch).

Now I am confused, because heightForRowAtIndexPath seems to be called for all cells in the table, even the cells that are not currently within viewport.

See the following log (the first number is the section index, the second is the row index):

2013-12-12 13:00:29.322 MyApp[32603:80b] GetHeightForRow - 1 - 0
2013-12-12 13:00:29.323 MyApp[32603:80b] GetHeightForRow - 1 - 1
2013-12-12 13:00:29.323 MyApp[32603:80b] GetHeightForRow - 1 - 2
2013-12-12 13:00:29.323 MyApp[32603:80b] GetHeightForRow - 1 - 3
2013-12-12 13:00:29.324 MyApp[32603:80b] GetHeightForRow - 1 - 4
2013-12-12 13:00:29.324 MyApp[32603:80b] GetHeightForRow - 1 - 5
2013-12-12 13:00:29.325 MyApp[32603:80b] GetHeightForRow - 1 - 6
2013-12-12 13:00:29.325 MyApp[32603:80b] GetHeightForRow - 1 - 7
2013-12-12 13:00:29.326 MyApp[32603:80b] GetHeightForRow - 1 - 8
2013-12-12 13:00:29.326 MyApp[32603:80b] GetHeightForRow - 1 - 9
2013-12-12 13:00:29.326 MyApp[32603:80b] GetHeightForRow - 1 - 10
2013-12-12 13:00:29.327 MyApp[32603:80b] GetHeightForRow - 1 - 11
2013-12-12 13:00:29.327 MyApp[32603:80b] GetHeightForRow - 1 - 12
2013-12-12 13:00:29.328 MyApp[32603:80b] GetHeightForRow - 1 - 13
2013-12-12 13:00:29.328 MyApp[32603:80b] GetHeightForRow - 1 - 14
2013-12-12 13:00:29.329 MyApp[32603:80b] GetHeightForRow - 1 - 15
2013-12-12 13:00:29.329 MyApp[32603:80b] GetHeightForRow - 1 - 16
2013-12-12 13:00:29.330 MyApp[32603:80b] GetHeightForRow - 1 - 17
2013-12-12 13:00:29.330 MyApp[32603:80b] GetHeightForRow - 1 - 18
2013-12-12 13:00:29.330 MyApp[32603:80b] GetHeightForRow - 1 - 19
2013-12-12 13:00:29.331 MyApp[32603:80b] GetHeightForRow - 1 - 20
2013-12-12 13:00:29.331 MyApp[32603:80b] GetHeightForRow - 1 - 21
2013-12-12 13:00:29.331 MyApp[32603:80b] GetHeightForRow - 1 - 22
2013-12-12 13:00:29.332 MyApp[32603:80b] GetHeightForRow - 1 - 23
2013-12-12 13:00:29.332 MyApp[32603:80b] GetHeightForRow - 1 - 24
2013-12-12 13:00:29.332 MyApp[32603:80b] GetHeightForRow - 0 - 0
2013-12-12 13:00:29.333 MyApp[32603:80b] GetHeightForRow - 0 - 1
2013-12-12 13:00:29.335 MyApp[32603:80b] GetCell - 0 - 0
2013-12-12 13:00:29.344 MyApp[32603:80b] GetCell - 0 - 1
2013-12-12 13:00:29.347 MyApp[32603:80b] GetCell - 1 - 0
2013-12-12 13:00:29.349 MyApp[32603:80b] GetCell - 1 - 1
2013-12-12 13:00:29.351 MyApp[32603:80b] GetCell - 1 - 2
2013-12-12 13:00:29.354 MyApp[32603:80b] GetCell - 1 - 3
2013-12-12 13:00:29.356 MyApp[32603:80b] GetCell - 1 - 4
2013-12-12 13:00:29.358 MyApp[32603:80b] GetCell - 1 - 5
2013-12-12 13:00:29.361 MyApp[32603:80b] GetCell - 1 - 6
2013-12-12 13:00:29.363 MyApp[32603:80b] GetCell - 1 - 7

Is there a way to not create all the content views before rendering the table, something I just don't see yet? Or is my basic assumption wrong, that this would be the best way regarding performance to not create all content views before?

Thanks

Basically TableViews normally work like this:

Cells are created when needed, that is, only the number of cells shown on screen are created. This is because allocating and initiating objects is expensive. Then, when the user scrolls, cells are dequeued from the table view and the new content is added to that cell.

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath is called for each row in a table view, regardless of whether the cells will be shown or not. (See Apple doc ). Apple also mentions that this has some performance issues with table views holding more than 1000 rows.

The best solution is usually to have one reuse identifier for each type of cell. Say you have a HighCell and a LowCell , then you'll figure out which type of cell you need for the current row (In the cellForRowAtIndexPath ) and dequeue that type of cell. Or even better, use - (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier ( Apple doc )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM