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?
我有一个小的、固定大小的表,我想把UITableView完全加载到内存中,并且如果单元格滚动到视图之外,就不要重用它们。我如何做到这一点?
I'm not using a UITableViewController; just a simple UIViewController that implements the proper protocols (UITableViewDataSource and UITableViewDelegate).
我没有使用UITableViewController;一个简单的UIViewController实现合适的协议(UITableViewDataSource和UITableViewDelegate)。
6 个解决方案
#1
18
Set nil
for reuse identifier in the line
为该行中的重用标识符设置nil。
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
Or just remove the line and add,
或者去掉这条线,
UITableViewCell *cell = nil;
#2
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.
不要实现方法UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SomeID"];而且,您的任何单元都不会被重用。每当它请求单元格时,您就创建一个新的单元格并对其进行配置。
#3
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
.
您应该在initWithStyle:reuseIdentifier方法中传递nil:如果您不想重用单元格,但请记住性能。只要它是好的,你应该可以通过nil。
#4
5
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):
前三个答案是完全正确的,您只需要确保不调用UITableView上的dequeueReusableCellWithIdentifier函数。除此之外,您还可以简单地在代码中分配单元格。首先,您需要一个实例变量来存储指向单元格的指针(我假设您使用的是普通视图控制器):
@interface MyViewController
@property (nonatomic, strong) NSArray* myTableViewCells;
@end
Then you can lazily instantiate this array, by overriding it's getter:
然后你可以延迟实例化这个数组,通过覆盖它的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.
如果愿意,可以向数组中添加更多的单元格,或者使用NSMutableArray。现在你要做的就是将这个数组连接到正确的UITableViewDataSource方法。
- (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.
添加新单元也容易得多(不需要切换或如果需要语句),代码的结构也更合理。
#5
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:).
有时你需要一些单元格是静态的,例如,你需要第一个单元格来下载有下载进度条的单元格。以及其他等待下载单元格的单元格。在本例中,第一个单元格应该可用于暂停和恢复函数(表视图外部:cellForRowAtIndexPath:)。
you could try to create static cells like this:
您可以尝试创建这样的静态单元格:
1st: subclass UITableViewCell, to create your own cell (this is a option)
1: UITableViewCell子类,创建您自己的单元格(这是一个选项)
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)
第三:viewDidLoad中的Init单元(viewDidLoad是一个很好的选择,用来放置Init代码)
- (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:
**如上所述,单元格创建一次,可以在tableView:cellForRowAtIndexPath:
You also could declare cells as @property to make it accessible for other class.
您还可以将单元格声明为@property,以使其他类可以访问它。
#6
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).
只需分配一个新的单元来代替dequeue,不需要执行上述任何操作。对于小的tableView(< 100个单元格),性能影响可以忽略不计。
Example in swift 3
在斯威夫特3例
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier:"Cell")
return cell
}
Cheers
干杯
#1
18
Set nil
for reuse identifier in the line
为该行中的重用标识符设置nil。
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
Or just remove the line and add,
或者去掉这条线,
UITableViewCell *cell = nil;
#2
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.
不要实现方法UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SomeID"];而且,您的任何单元都不会被重用。每当它请求单元格时,您就创建一个新的单元格并对其进行配置。
#3
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
.
您应该在initWithStyle:reuseIdentifier方法中传递nil:如果您不想重用单元格,但请记住性能。只要它是好的,你应该可以通过nil。
#4
5
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):
前三个答案是完全正确的,您只需要确保不调用UITableView上的dequeueReusableCellWithIdentifier函数。除此之外,您还可以简单地在代码中分配单元格。首先,您需要一个实例变量来存储指向单元格的指针(我假设您使用的是普通视图控制器):
@interface MyViewController
@property (nonatomic, strong) NSArray* myTableViewCells;
@end
Then you can lazily instantiate this array, by overriding it's getter:
然后你可以延迟实例化这个数组,通过覆盖它的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.
如果愿意,可以向数组中添加更多的单元格,或者使用NSMutableArray。现在你要做的就是将这个数组连接到正确的UITableViewDataSource方法。
- (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.
添加新单元也容易得多(不需要切换或如果需要语句),代码的结构也更合理。
#5
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:).
有时你需要一些单元格是静态的,例如,你需要第一个单元格来下载有下载进度条的单元格。以及其他等待下载单元格的单元格。在本例中,第一个单元格应该可用于暂停和恢复函数(表视图外部:cellForRowAtIndexPath:)。
you could try to create static cells like this:
您可以尝试创建这样的静态单元格:
1st: subclass UITableViewCell, to create your own cell (this is a option)
1: UITableViewCell子类,创建您自己的单元格(这是一个选项)
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)
第三:viewDidLoad中的Init单元(viewDidLoad是一个很好的选择,用来放置Init代码)
- (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:
**如上所述,单元格创建一次,可以在tableView:cellForRowAtIndexPath:
You also could declare cells as @property to make it accessible for other class.
您还可以将单元格声明为@property,以使其他类可以访问它。
#6
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).
只需分配一个新的单元来代替dequeue,不需要执行上述任何操作。对于小的tableView(< 100个单元格),性能影响可以忽略不计。
Example in swift 3
在斯威夫特3例
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier:"Cell")
return cell
}
Cheers
干杯