Disable cell reuse for small fixed-size UITableView
Asked Answered
B

6

30

I have a small, fixed-size table, and I want to load UITableView entirely into memory, and never reuse cells if they scroll out of view. How do I achieve this?

I'm not using a UITableViewController; just a simple UIViewController that implements the proper protocols (UITableViewDataSource and UITableViewDelegate).

Broomfield answered 22/6, 2011 at 16:49 Comment(0)
B
19

Set nil for reuse identifier in the line

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];

Or just remove the line and add,

UITableViewCell *cell = nil;
Bell answered 22/6, 2011 at 17:5 Comment(1)
That's dequeueReusableCellWithIdentifier not dequeueCellWithReuseIdentifierCrookes
T
7

Just do not implement the method UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SomeID"]; and none of your cells will be reused. Each time it ask for a cell you create a new one and configure it.

Thirlage answered 22/6, 2011 at 16:55 Comment(0)
K
6

You should pass nil in the method initWithStyle:reuseIdentifier: if you don't want to reuse cells but keep in mind the performance. As long as it is good, you should be ok passing nil.

Kaminsky answered 22/6, 2011 at 16:56 Comment(0)
B
6

First three answers are completely correct, you just need to make sure that you do not call dequeueReusableCellWithIdentifier function on a UITableView. In addition to this, you can simply allocate the cells in code. First you will need an instance variable that will store the pointers to your cells (I will assume you use a normal view controller):

@interface MyViewController

@property (nonatomic, strong) NSArray* myTableViewCells;

@end

Then you can lazily instantiate this array, by overriding it's getter:

- (NSArray *)myTableViewCells
{
    if (!_myTableViewCells)
    {
        _myTableViewCells = @[ 
                                [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil],
                                [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]
                             ];
    }

    return _myTableViewCells;
}

Add more cells into array if you like, or use NSMutableArray. Now all you have to do is to wire up this array to proper UITableViewDataSource methods.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.myTableViewCells.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell* cell = self.myTableViewCells[indexPath.row];

    //
    // Add your own modifications
    //

    return cell;
}

This makes for a much cleaner code, less prone to memory leaks (static variables get deallocated when program ends, so why are we keeping table view cells in memory if the view controller that is displaying them is already gone?).

The addition of new cells is also much easier (no switch or if statements required) and code is more nicely structured.

Brachium answered 13/7, 2014 at 9:33 Comment(0)
P
2

EDITED

Sometimes you need some cells to be static, for example, you need the first cell to be downloading cell which has download progress bar. and other cells to be waiting for download cells. In this case, the first cell should be accessible for pause and resume functions(outside tableView:cellForRowAtIndexPath:).

you could try to create static cells like this:

1st: subclass UITableViewCell, to create your own cell (this is a option)

2nd: crate static cell in your view controller

static YourSubclassedTableViewCell *yourCell_0;
static YourSubclassedTableViewCell *yourCell_1;
static YourSubclassedTableViewCell *yourCell_2;
static YourSubclassedTableViewCell *yourCell_3;

3rd: Init cells in viewDidLoad (viewDidLoad is a good choice to put init code)

- (void)viewDidLoad
{
    yourCell_0 = [[YourSubclassedTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
    yourCell_1 = [[YourSubclassedTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
    yourCell_2 = [[YourSubclassedTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
    yourCell_3 = [[YourSubclassedTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];

    // or simply
    yourCell_0 = [[YourSubclassedTableViewCell alloc] init];
    yourCell_1 = [[YourSubclassedTableViewCell alloc] init];
    yourCell_2 = [[YourSubclassedTableViewCell alloc] init];
    yourCell_3 = [[YourSubclassedTableViewCell alloc] init];

}

4th: Load cell

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    switch (indexPath.row) {
        case 0:
            yourCell_0.textLabel.text = @"1st Row";
            return yourCell_0;

        case 1:
            yourCell_1.textLabel.text = @"2nd Row";
            return yourCell_1;

        case 2:
            yourCell_2.textLabel.text = @"3rd Row";
            return yourCell_2;

        case 3:
            yourCell_3.textLabel.text = @"4th Row";
            return yourCell_3;

        default:
            defaultCell....(ignore)
            return defaultCell;
    }
}

**As described above, cells are created once and can be accessed outside tableView:cellForRowAtIndexPath:

You also could declare cells as @property to make it accessible for other class.

Plainsong answered 13/7, 2014 at 8:25 Comment(4)
This is a bad solution, why would you need static cells, when you can easily create your own array of cells in current instance of the UIViewController?Brachium
Sometimes you need some cells to be static, for example, you need the first cell to be downloading cell which has download progress bar. and other cells to be waiting for download cells. In this case, the first cell should be accessible for pause and resume functions(outside tableView:cellForRowAtIndexPath:). You could also make the cell as @property.Plainsong
I'm not entirely sure you know what static means. I'm not even sure what you mean with other cells waiting for download cells. For download to complete or? In MVC pattern, the model should be downloading, not cells, which are clearly on View layer. It is just not the correct way. Property would be a more correct way, indeed.Brachium
You are right! In MVC design pattern, Views can, but better not to play the role of a View Controller.Plainsong
B
2

Just alloc a new cell in place of dequeue no need to do any of the above. Performance implications are negligible for small tableView (< 100 cells).

Example in swift 3

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = UITableViewCell(style: .default, reuseIdentifier:"Cell")
    return cell
}

Cheers

Buchan answered 3/1, 2017 at 1:15 Comment(1)
Outlets in the cell object are are nil when creating the cell this way, for me.Malva

© 2022 - 2024 — McMap. All rights reserved.