1. 程式人生 > >UITableView的cell複用,UICollectionView的cell複用

UITableView的cell複用,UICollectionView的cell複用

關於UITableView的Cell複用談談我的一些心得

UITableView是ios開發中使用率極高的一個控制元件,就我個人來說,幾乎我做的每一個View上都有她的身影。但是很長一段時間,我對她的理解都很膚淺。對我來說觸動較大的兩個東西,一個是前面提到的自定義UITableViewCell,再有就是今天要提的這個複用了。
所謂複用表面意思來理解就是重複利用了。大致的工作原理就是:UITableView屬於lazy loading,也就是隻載入會在介面上顯示的部分。舉個例子,比如說UITabeview的高度是460,咱們每個Cell的高度是230,這樣的話, 手機介面上最多就顯示兩個Cell,當你向上划動,第一個Cell一些離開介面,第三個Cell的一些出現在介面的時候會再建立第三個Cell。注意關鍵 部分到了,再第二個Cell開始離開介面,第四個Cell出現的時候,這時候不會建立第四個Cell,而是直接複用的第一個Cell!也就是說無論你的 UITableView裡有十條或者三十條資料,只會建立三個Cell來展示這些資料!

總的來說,這種工作機制很合理,無論從CPU和記憶體的角度考慮都很節省資源,但是這裡有一個問題就是:這種機制是用來展示結構一樣的資料的!很多時候我們 總要實現動態載入,總要有一個Cell,與其它的Cell不同,用來顯示“正在載入中”或者“載入更多”之類的東西。這時候在Cell複用的機制下會出現 重疊的現像!
ok,光說不練,沒啥用,簡單演示一下:

 _objects = [[NSMutableArray alloc] init];
 for (int i = 0; i < 10; i++) {
 [_objects addObject:[NSString stringWithFormat:@"text %d",i]];
 }
 [_objects addObject:@"載入更多"];
 for (int i = 0; i < 10; i++) {
 [_objects addObject:[NSString stringWithFormat:@"text %d",i]];
 }
我們在一個數組裡加了21條資料,而且中間那條不一樣,屬於我們說的資料結構不一致的那種。
cell展示部分我們是這麼寫的:

 NSString *_text = [_objects objectAtIndex:indexPath.row];

 //我們希望“載入更多”這行是居中顯示
 if (![_text hasPrefix:@"text"]) {
 cell.textLabel.textAlignment = UITextAlignmentCenter;
 }

 cell.textLabel.text = _text;
ok,我們執行一下:


向下拖動一下,目前看來是沒有問題的。可是當我們上下拖動了幾次以後,問題出現了。。




由於cell的複用機制,“文字居中”(UITextAlignmentCenter)這種屬性漸漸的被其它Cell用上了。這個腫麼辦呢?最早的時候,我通過了網上搜索,大家都說這是Cell的複用的問題。而我想當然的認為,既然是複用,那我就不復用就好了。於是我把

 if (cell == nil) {
 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
 }
改成了:
 if (cell != nil) {
 [cell release];
 }
 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
是的,在我這麼改完以後,UITableView看起來確實是按我想的方式工作了,事實上很長的時間裡都沒再出過錯。(不要問我為什麼不在if後面 跟個else把文字的屬性設成“文字居左”(UITextAlignmentLeft),因為實際的資料比這複雜的多。)這種方法一直工作的很ok(確切 的說是在iphone4上),直到很久以後,我把同樣的程式在itouch上一跑,沒載入多少條資料就提示Received memory warning了。。。。。
所以我知道了正確的Cell複用的方式:
 NSString *_text = [_objects objectAtIndex:indexPath.row];

 UITableViewCell *cell;
 if ([_text hasPrefix:@"text"]) {
 static NSString *CellIdentifier = @"Cell";

 cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
 if (cell == nil) {
 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
 }
 }
 else {
 static NSString *CellIdentifier = @"CellReuse";

 cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
 if (cell == nil) {
 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
 }

 cell.textLabel.textAlignment = UITextAlignmentCenter;
 }

 cell.textLabel.text = _text;