在UITableView当中,通常都会对cell进行重用
UITableViewCell *cell = [tabledequeueReusableCellWithIdentifier:identifierforIndexPath:indexPath];
这个方法想必大家都不陌生。这是苹果提供给我们在tableView需要大量的数据项时,一个优化内存的机制。
但是,因为这个机制,使我在tableViewCell重用时遇到很大的问题。就是cell之间相互干扰。
在屏幕上的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这种方法很奇葩,感觉就像我要剪手指甲,本来需要指甲刀,苹果给我一把西瓜刀,我还一定要用西瓜刀来剪指甲。。。这种方法是自己想出来,如果有一些简单的,或者比较规范的方法,希望能够告知。。。