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