Disable cell reuse for small fixed-size UITableView
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 开发者_Python百科using a UITableViewController; just a simple UIViewController that implements the proper protocols (UITableViewDataSource and UITableViewDelegate).
Set nil
for reuse identifier in the line
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
Or just remove the line and add,
UITableViewCell *cell = nil;
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.
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
.
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.
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.
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
精彩评论