UITableView: load all cells
Asked Answered
G

5

5

Is it possible to load all cells of an UITableView when the view is loaded so that they are not loaded when I'm scrolling? (I would show a loading screen while doing this)

Please, it's the only way at my project (sorry too complicate to explain why ^^)

EDIT:

Okay let me explain you, what I'm definite doing:

- (UITableViewCell *)tableView:(UITableView *)tableView
     cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   NSString *cellIdentifier = [NSString stringWithFormat:@"Identifier %i/%i", indexPath.row, indexPath.section];
   CustomTableCell *cell = (CustomTableCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
   NSDictionary *currentReading;

   if (cell == nil)
   {
       cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];

       UILabel *label;
       UIView *separator;

       if(indexPath.row == 0)
       {
           // Here I'm creating the title bar of my "table" for each section
       }
       else
       {
           int iPr = 1;

           do
           {
               currentReading = [listData objectAtIndex:iPr-1];
               iPr++;
           } while (![[currentReading valueForKey:@"DeviceNo"] isEqualToString:[devicesArr objectAtIndex:indexPath.section]] || 
                      [readingresultsArr containsObject:[currentReading valueForKey:@"ReadingResultId"]]);

           [readingresultsArr addObject:[currentReading valueForKey:@"ReadingResultId"]];
           //
           // ...
           //
       }
    }
    return cell;
}

My error happens in the do-while-loop: "listData" is an array with multiple dictionaries in it. My problem ist that when I’m scrolling my table slowly down, all is fine, but when I’m scrolling quickly to the end of the view and then I’m scrolling to the middle, I get the error that iPr is out of the array’s range. So the problem is, that the last row of the first section has already been added to the "readingresultsArr", but has not been loaded or wants to be loaded again. That’s the reason why I want to load all cells at once.

Geisel answered 4/9, 2012 at 17:49 Comment(3)
"Please, it's the only way at my project" - it certainly shouldn't be. And please explain, even if it's complicated. Apart from this not being possible, it's also terrible wrong parctice in terms of memory management.Verge
@H2CO3 I've edited my question and described my problem in more detail. Hope you can help me.Geisel
Could you explain what you're trying to accomplish with the do...while loop? It looks like you're trying to find an object meeting some criteria, and then building up a new array on the fly out of that, but why do you need to do that there? Can you build that array before reloading the table?Trichloromethane
B
11

You can cause all of the cells to be pre-allocated simply by calling:

[self tableView: self.tableView cellForRowAtIndexPath: indexPath];

for every row in your table. Put the above line in an appropriate for-loop and execute this code in viewDidAppear.

The problem however is that the tableView will not retain all of these cells. It will discard them when they are not needed.

You can get around that problem by adding an NSMutableArray to your UIViewController and then cache all the cells as they are created in cellForRowAtIndexPath. If there are dynamic updates (insertions/deletions) to your table over its lifetime, you will have to update the cache array as well.

Blanc answered 4/9, 2012 at 23:6 Comment(5)
This was the answer I was searching for :) You are my hero! Big thanks! But also thanks to the other ones for their help.Geisel
I originally said use an NSMutableArray, but NSDictionary would probably be better since you can use the indexPath.row as the key. NSMutableArray won't let you add things out of order.Blanc
Yes I have used NSDictionary with a string like "indexPath.row/indexPath.section" as key. But you brought me in the right direction, thanks :) PS: [self.tableView tableView: self.tableView cellForRowAtIndexPath: indexPath]; should be without the first ".tableView" in your answerGeisel
@Blanc hey so im having the reverse problem. all my cells are being loaded into memory and cellforrowatindexpath is being called and im not calling it manually. why is this?Barbra
causing memory issue, cells are not getting the release from memorySpotted
G
9

put a uitableview on a uiscrollview

for example , you expect the height of the full list uitableview is 1000

then set the uiscrollview contentsize is 320X1000 and set the uitableview height is 1000

then all cell load their content even not visible in screen

Garboil answered 28/5, 2013 at 2:17 Comment(3)
Perfect recipe for troubles.Lowell
Thanks for this comment. Was wondering why a table view was always loading all of it's rows, yep, it is under a scroll view. Not sure why this is, but ok, have to rework the UITisman
@highmaintenance problem is not with the answer but with the question. this answer gets job done, need also to disable scroll of tableview.Townspeople
Z
3

In my case it was that I used automaticDimension for cells height and put estimatedRowHeight to small that is why tableview loaded all cells.

Zobias answered 19/2, 2019 at 11:53 Comment(3)
Welcome to Stack Overflow. :-) Could you provide an example?Mortenson
Please provide code snippet understand your answer more better wayOdyssey
What @Zobias mentions is not a solution to the question, however, it's a very good trick if you need to preload some more cells than the one being rendered in the screen while using automaticDimension. This trick has been useful to me sometimes in which I have a tableview with some complex cells but I only have like 4 or 5 cells. If I set a low value for estimatedRowHeight, the tableview will preload all the cells since it expects them to be visible. After this, when I scroll to the bottom all the cells where already preloaded by the system. If use high values, it will feel laggy.Staffard
I
0

Following the comment that was made by juancazalla, I found that if you have a tableView that is using automaticDimension, loading all the cells at once can be best achieved by setting estimatedRowHeight to a low value (such as 1).

Inhaul answered 19/4, 2020 at 1:20 Comment(0)
M
0

Some of the answers here and here suggest using automaticDimension for cells height and put mytable.estimatedRowHeight to a very low value (such as 1).


Starting with iOS 15 this approach seems not to work anymore. Hence, another way to achieve the table to "load" all cells could be by automatically scrolling to the last cell. Depending on the tables height and how many rows it can show some cells are discarded but each cell would be loaded and shown at least once.

mytable.scrollEnabled = YES;
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:cellCount - 1 inSection:0];
[mytable scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
mytable.scrollEnabled = NO;

If you want to scroll up again just scroll to the top as outlined here.

Mejia answered 14/10, 2022 at 6:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.