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.

Undo
  • 25,519
  • 37
  • 106
  • 129
Michael
  • 105
  • 1
  • 3
  • 9
  • 6
    "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. –  Sep 04 '12 at 17:52
  • @H2CO3 I've edited my question and described my problem in more detail. Hope you can help me. – Michael Sep 04 '12 at 20:24
  • 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? – Carl Veazey Sep 04 '12 at 23:16

5 Answers5

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.

Kent
  • 1,691
  • 4
  • 19
  • 27
  • 1
    This was the answer I was searching for :) You are my hero! Big thanks! But also thanks to the other ones for their help. – Michael Sep 06 '12 at 19:44
  • 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. – Kent Sep 06 '12 at 19:54
  • 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 answer – Michael Sep 07 '12 at 08:34
  • @Kent 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? – Noah Passalacqua Sep 23 '14 at 00:17
  • causing memory issue, cells are not getting the release from memory – Suhas Arvind Patil Jun 29 '18 at 11:02
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

chings228
  • 1,859
  • 24
  • 24
  • 11
    Perfect recipe for troubles. – pronebird May 03 '14 at 20:37
  • 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 UI – ort11 Feb 12 '15 at 17:12
  • @highmaintenance problem is not with the answer but with the question. this answer gets job done, need also to disable scroll of tableview. – Alexander Danilov Mar 18 '19 at 17:59
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.

Bruno Bieri
  • 9,724
  • 11
  • 63
  • 92
Lina
  • 31
  • 1
  • Welcome to Stack Overflow. :-) Could you provide an example? – Jeppe Feb 19 '19 at 12:13
  • Please provide code snippet understand your answer more better way – TheParam Feb 19 '19 at 12:24
  • 2
    What @Lina 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. – juancazalla Mar 30 '19 at 16:41
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).

Bruno Bieri
  • 9,724
  • 11
  • 63
  • 92
Andrew
  • 1
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.

Bruno Bieri
  • 9,724
  • 11
  • 63
  • 92