UITableViewCell 的重用解決

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




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章