在UITableView当中,通常都会对cell进行重用

UITableViewCell *cell = [tabledequeueReusableCellWithIdentifier:identifierforIndexPath:indexPath];


这个方法想必大家都不陌生。这是苹果提供给我们在tableView需要大量的数据项时,一个优化内存的机制。

但是,因为这个机制,使我在tableViewCell重用时遇到很大的问题。就是cell之间相互干扰。

iOS collectionview复用性问题 ios tableview关闭cell复用_Apple

在屏幕上的cell都有一个UISwitch,假如每个UISwich都是关闭状态。而当我们打开了第一个,我们再向下滑动屏幕时,新出现的cell也会出现打开的情况。而很明显,每隔7个会出现一个打开的UISwitch。这就是dequeReusable的作用。

OK,查阅很多文章后的解决方案

1. 将每个cell的identifier都改为不一样,这样自然不会重用

2. 在每次cellForRowAtIndexPath读取时,对cell的显示数据进行设置

这里采用的是第二种方法。

先说思想。我们在持有这个table的controller中对每个cell里面的组件的状态都进行保存到NSMutableDictionary,这里只有UISwitcher。

然后每次在cellForRowAtIndexPath中,我们都从dictionary中读出数据,填充到cell里面。

每次我们将某个cell的UISwitch打开或关闭时,都即时将cellUISwitch的状态存到dictionary里面。

下面把代码贴出来

1. 在UITableViewCell子类中,典型的代理模式


@protocol LLDCustomCellDelegate <NSObject>

-(void)toggle:(id)sender; //switch状态改变

@end

@interface LLDCustomCell : UITableViewCell

@property (strong, nonatomic) UISwitch *switcher;
@property (strong, nonatomic) id<LLDCustomCellDelegate> delegate;


2. 在LLDCustomCell.m中,添加时间监听

[switcher addTarget:self action:@selector(switcherChanged) forControlEvents:UIControlEventValueChanged];




-(void)switcherChanged{
    [delegate toggle:self];	//委托代理来实现
}



3. 在controller头文件中


@interface LLDMainViewController : UIViewController
  <UITableViewDataSource,UITableViewDelegate,LLDCustomCellDelegate>

@property (copy, nonatomic) NSArray *dataList;	//每个cell的标题
@property (copy, nonatomic) NSMutableDictionary *dataDic;	//保存cell组件的状态
@property (strong, nonatomic) UITableView *table;

@end

4. 下面就分别贴出controller的必要方法


-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    LLDCustomCell *cell = [table dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
    cell.textLabel.text = [dataList objectAtIndex:[indexPath row]];
    cell.switcher.on = [[dataDic objectForKey:cell.textLabel.text]boolValue]; //读组件的状态
    cell.delegate = self;	//将自己作为cell的委托
    return cell;
}

 controller实现LLDCustomCell的委托方法


-(void)toggle:(id)sender{
    LLDCustomCell *cell = (LLDCustomCell *)sender;
    NSString *key = cell.textLabel.text;
    [dataDic setValue:[NSNumber numberWithBool:cell.switcher.on] forKey:key];	//存数据
}

在这里程序就完成了。dataDic保存了当前的cell的状态,在加载cell的时候,就从dataDic当中把状态读出来。这样就解决了因为“重用”而带来的冲突问题。始终觉得为每一个cell都创建不同的identifier这种方法很奇葩,感觉就像我要剪手指甲,本来需要指甲刀,苹果给我一把西瓜刀,我还一定要用西瓜刀来剪指甲。。。这种方法是自己想出来,如果有一些简单的,或者比较规范的方法,希望能够告知。。。