在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;
[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這種方法很奇葩,感覺就像我要剪手指甲,本來需要指甲刀,蘋果給我一把西瓜刀,我還一定要用西瓜刀來剪指甲。。。這種方法是自己想出來,如果有一些簡單的,或者比較規範的方法,希望能夠告知。。。