02.1.1.tableView性能优化 - cell的重用
方法一
/**
* 什么时候调用:每当有一个cell进入视野范围内就会调用
*/
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 0.重用标识
// 被static修饰的局部变量:只会初始化一次,在整个程序运行过程中,只有一份内存
static NSString *ID = @"cell";
// 1.先根据cell的标识去缓存池中查找可循环利用的cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 2.如果cell为nil(缓存池找不到对应的cell)
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
}
// 3.覆盖数据
cell.textLabel.text = [NSString stringWithFormat:@"testdata - %zd", indexPath.row];
return cell;
方法二
tableView: cellForRowAtIndexPath:方法中有两个获得重用cell的方法
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
和
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]
- 定义一个全局变量
// 定义重用标识
NSString *ID = @"cell";
- 注册某个标识对应的cell类型
// 在这个方法中注册cell
- (void)viewDidLoad {
[super viewDidLoad];
// 注册某个标识对应的cell类型
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:ID];
}
- 在数据源方法中返回cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1.去缓存池中查找cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 2.覆盖数据
cell.textLabel.text = [NSString stringWithFormat:@"testdata - %zd", indexPath.row];
return cell;
}
新的重用机制
- (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(5_0);
- (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0);
//需要使用dequeueReusableCellWithIdentifier:forIndexPath:注册的必须实现上面两个注册中的一种
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
}
http://www.07net01.com/program/565558.html
今天在学习IAP的时候无意间看到原来
tableView: cellForRowAtIndexPath:方法中有两个获得重用cell的方法,
一直以来都是用
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
那下面的这个怎么用呢,感觉比较怪,假设没有重用的岂不是为空了
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]
具体有什么区别呢,
并且当我用
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]的时候,为什么总报错
reason: 'unable to dequeue a cell with identifier Cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard',
经过查阅,知道原来此方法为6.0新加的,在SDK5.0是运行不起来的。 如果需要使用这个方法,你必须使用配套的方法来一起用,下面两个配套方法选其一:
- (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(5_0);
- (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0);
比如你已经用NIB做了一个Cell,或者自定义了一个Cell。我们在你创建UITableView的时候,就可以顺带
self.tableView.backgroundColor = xxxx;
[self.tableView registerClass:[CustomCell class] forCellReuseIdentifier:@"CustomCell"];
这样你在- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath这个方法里,你就可以省下这些代码:
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
//设置你的cell
}
而只需要
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
//设置你的cell
整体来说6.0却是比5.0更省劲
方法三
- 在storyboard中设置UITableView的Dynamic Prototypes Cell
- 设置cell的重用标识
- 在代码中利用重用标识获取cell
// 0.重用标识
// 被static修饰的局部变量:只会初始化一次,在整个程序运行过程中,只有一份内存
static NSString *ID = @"cell";
// 1.先根据cell的标识去缓存池中查找可循环利用的cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 2.覆盖数据
cell.textLabel.text = [NSString stringWithFormat:@"cell - %zd", indexPath.row];
return cell;
注意事项
重用的时候一些东西可能没清空 最好在赋值的时候把清空 重写
-(void)setStatus:(Status *)status{
_status = status;
if (status.isVip) {
self.nameLabel.textColor = [UIColor orangeColor];
self.vipView.hidden = NO;
} else {
self.nameLabel.textColor = [UIColor blackColor];
self.vipView.hidden = YES;
}
self.nameLabel.text = status.name;
self.iconView.image = [UIImage imageNamed:status.icon];
if (status.picture) {
self.pictureView.hidden = NO;
self.pictureView.image = [UIImage imageNamed:status.picture];
} else {
self.pictureView.hidden = YES;
}
self.contentLabel.text = status.text;
}
dequeueReusableCellWithIdentifier: forIndex: 方法是IOS6.0+版本才出现的,新的重用机制方法;只能在IOS 6.0以上系统才有效;
注意官方SDK说明: newer dequeue method guarantees a cell is returned and resized properly, assuming identifier is registered 即:使用dequeueReusableCellWithIdentifier: forIndex: 必须使用配套的
- (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier
或者
- (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier这个方法。对每一个tableview的cell进行注册。