UITableViewCell 的重用问题。

我每个 cell 里面都有一个 button,我为 button 设置了一个点击响应动作 btn_tapped

btn_tapped 里面我把 sender 转换成 button 对象,并操作它:比如设置为隐藏。但是发现跟它共用同一个内存 button 也隐藏起来了。

有没有什么方法可以拿到 button 并且设置属性又不冲突的?

回答:

在复用TableView的时候,一定要从数据源的角度出发。

以咱们这个问题为例,比如,我们的tableView数据源是timelineArray,保存着一个timeline列表。假如Button是“赞”这个按钮的话,我们之所以要展示这个“赞”按钮,是因为当前这条timeline中的isLiked(是否被赞)属性为NO.所以这样写:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

BtnTableViewCell *cell = (BtnTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"BtnTableViewCell"];

NSDictionary* timeline = [self.timelines objectAtIndex:indexPath.row];

BOOL isLiked = [[timeline objectForKey:@"isLiked"] boolValue];

//tableViewCell的样式是和数据源有关的,所以我们是根据数据源来确定样式。为了阅读方便写成下面这样,其实是可以写成一行:cell.likeButton.hidden = !isLiked;

if (isLiked) {

cell.likeButton.hidden = YES;

}else{

cell.likeButton.hidden = NO;

}

//我们最好再给button再加一个tag,方便标识之后点击的时候确定点击了哪条timeline

cell.likeButton.tag = indexPath.row;

return cell;

}

因为在滑动tableview时,就是通过cellForRowAtIndexPath来复用cell的,所以数据源的改变,cell的样式也会改变。同时,我们进行任何操作时,本来就会更新数据源的最新状态,这是最正确的做法。

- (void)btn_tapped:(id)sender

{

if(![sender isKindOfClass:[UIButton class]){

return;

}

UIButton *btn = (UIButton*)sender;

//通过tag来获取到timeline的index

NSInteger row = btn.tag;

//【1】立即隐藏该按钮;

btn.hidden = YES;

//【2】标记数据源,例如保存这条消息已经被赞过了,方便接下来复用cell时识别

NSMutableDictionary *timeline = [self.timelines objectAtIndex:row];

[timeline setObject:[[NSNumber alloc] initWithBool:YES] forKey:@"isLiked"];

}

回答:

你应该在点击之后把是否显示按钮的状态存起来,再reload TableView, 在tablveiw获取cell的代理方法时通过你存的是否要显示的状态来显示或者隐藏按钮

回答:

因为没有具体的代码,所以以下是我觉得可以解决的方案。

猜测问题:cell的重用机制造成了公用内存。

解决问题应该从重用方式上考虑。(可以自己搜索如何解决重用,应该有3种方法)

主要的解决办法就是CellIdentifier定义成不同的。

--------

我写了一个小例子

原始状态:

图片描述

点击btn后的状态(隐藏一个btn)

图片描述

目录文件:

图片描述


table代码

主要代码在-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;如下:

cpp-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

//定义不同的CellIdentifier

NSString *CellIdentifier = [NSString stringWithFormat:@"cell%i%i",indexPath.section,indexPath.row];

//绑定CellIdentifier

BtnTableViewCell *cell = (BtnTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil) {

NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"BtnTableViewCell" owner:self options:nil];

cell = [topLevelObjects objectAtIndex:0];

}

return cell;

}

cell中的代码:

BtnTableViewCell.h中:

cpp@interface BtnTableViewCell : UITableViewCell

@property (weak, nonatomic) IBOutlet UIButton *cellBtn;

@property (weak, nonatomic) IBOutlet UILabel *cellTitle;

@end

BtnTableViewCell.m文件代码:

cpp- (void)awakeFromNib {

[self.cellBtn addTarget:self action:@selector(btn_tapped:) forControlEvents:UIControlEventTouchUpInside];

}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {

[super setSelected:selected animated:animated];

}

- (void)btn_tapped:(id)sender

{

UIButton *btn = sender;

btn.hidden = YES;

}


这样实现的效果就可以点击一个btn,让其隐藏,而且还可以尽量减少内存的使用。

不知道是否解决你的问题,如有问题,请继续提问。

不知道为什么就是排不好版面了。

回答:

一楼说得好。即然是复用,那就应该把他从脑子里列出来。它只是装载数据的容器,一切属性都应该取决于他所装载的数据。所以变动的时候首先想到的应该是变动它的数据源,然后再刷新容器。

以上是 UITableViewCell 的重用问题。 的全部内容, 来源链接: utcz.com/p/186436.html

回到顶部