轉(zhuǎn)自:http://www.2cto.com/kf/201207/144337.html
今天在看iphone開發(fā)秘籍的時候尘盼,遇到這個問題,就仔細(xì)的深入了一下烦绳,通過測試卿捎,獲取了一些自認(rèn)為還不錯的結(jié)論,希望對大家在cell復(fù)用方面遇到的一些問題會有所幫助径密。
本篇文章只講原理午阵,對于如果對cell做界面,不深入講述。鑒于我的表達(dá)能力有限底桂,可能會有我自己清楚植袍,但是卻說不清楚的地方,如有問題籽懦,留言給我于个。
UITableView在界面的編程用的甚多,iphone開發(fā)也三月有余了暮顺,每次用到cellForRowAtIndexPath的委托方法的時候厅篓,都是直接copy代碼,自己略加一些界面的修改捶码,對于cell的標(biāo)示符都是static NSString* identifier = @"cell";然后調(diào)用dequeueReusableCellWithIdentifier方法獲取cell贷笛,如果cell為空,再調(diào)用[[[UITableViewCellalloc]initWithStyle方法新創(chuàng)建一個宙项,根本沒有考慮過更深一些的東西乏苦。為了講解清楚,現(xiàn)放上一段代碼尤筐,代碼copy自iphone開發(fā)秘籍汇荐,本人為了講解,略加修改盆繁。以下所有講解均依照此代碼進(jìn)行掀淘,因此,如果您希望能夠透徹的了解cell的復(fù)用機(jī)制油昂,建議實(shí)際運(yùn)行以下革娄,跟著講解,查看效果冕碟。代碼只有tableVIew的委托方法拦惋,因此您需要自己創(chuàng)建工程,把這些委托方法加進(jìn)去安寺。
上文一共四個委托方法厕妖,表明tableView一個section,有32行挑庶,高度為58.關(guān)于tableView的高度那個委托方法的返回的高度值言秸,建議最好自己運(yùn)行程序查看以下,最終達(dá)到一頁的界面顯示8個cell迎捺,第8個cell顯示一半也行举畸,但是不能顯示9和7個cell。我這里之所以為58凳枝,由于(480 - 44)/ 58 為7.5 的樣子抄沮,44為navigationBar的高度,480為屏幕的高度『鲜牵總之,需要達(dá)到的效果是一頁顯示7個多的cell锭环。還有那個icon.png需要自己準(zhǔn)備了聪全,要把它顯示出來。是不是很麻煩呀辅辩?沒辦法难礼,誰讓我們在獲得知識呢,知識總是需要點(diǎn)功夫的玫锋。
[cpp]
- (NSInteger)numberOfSectionsInTableView:(UITableView *)aTableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section
{
return 32;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 58;
}
- (UITableViewCell *)tableView:(UITableView *)tView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCellStyle style;
NSString *cellType;
switch (indexPath.row % 4)
{
case 0:
style = UITableViewCellStyleDefault;
cellType = @"Default Style";
//有標(biāo)題沒有正文(沒有細(xì)節(jié)文字)蛾茉。可選的圖片
break;
case 1:
style = UITableViewCellStyleSubtitle;
cellType = @"Subtitle Style";
//標(biāo)題和正文方式撩鹿,上下排布谦炬。可選的圖片
break;
case 2:
style = UITableViewCellStyleValue1;
cellType = @"Value1 Style";
//左邊文字左對齊节沦,右邊文字右對齊键思。可選的圖片
break;
case 3:
style =UITableViewCellStyleValue2;
cellType =@"Value2 Style";
//左邊文字右對齊甫贯,藍(lán)色吼鳞;右邊文字左對齊,黑色叫搁。沒有圖片
break;
}
static int i = 0;
UITableViewCell *cell = [tView dequeueReusableCellWithIdentifier:cellType];
if (!cell)
{
cell = [[[UITableViewCell alloc] initWithStyle:style reuseIdentifier:cellType] autorelease];
++i;
NSLog(@"cell created %d times", i);
}
if (indexPath.row > 3)
cell.imageView.image = [UIImage imageNamed:@"icon.png"];
cell.textLabel.text = cellType;
cell.detailTextLabel.text = @"Subtitle text";
return cell;
}
首先講解一下復(fù)用隊列:
復(fù)用隊列的元素增加:只有在cell被滑動出界面的時候赔桌,此cell才會被加入到復(fù)用隊列中。每次在創(chuàng)建cell的時候渴逻,程序會首先通過調(diào)用dequeueReusableCellWithIdentifier:cellType方法疾党,到復(fù)用隊列中去尋找標(biāo)示符為“cellType”的cell,如果找不到惨奕,返回nil仿贬,然后程序去通過調(diào)用[[[UITableViewCell alloc] initWithStyle:style reuseIdentifier:cellType] autorelease]來創(chuàng)建標(biāo)示符為“cellType”的cell。
先運(yùn)行一次程序墓贿,不要滑動cell茧泪,查看打印日志,會有打印"cell create 1 times",,,"cell create 8 times"聋袋,一共有8個日志队伟,表明cell創(chuàng)建了8次,這個日志打印是在cellForRowAtIndexPath中的創(chuàng)建cell的時候打印的幽勒。然后慢慢向下(向下的意思嗜侮,實(shí)際上是手向上滑動,讓界面顯示下一個cell,向上與之相反)滑動cell锈颗,到顯示第九個cell的時候顷霹,會看到打印一條日志"cell create 9 times",然后繼續(xù)慢慢向下滑動,會有"cell create 10 times"击吱,直到滑動到第12個cell以后淋淀,cell被創(chuàng)建了12個之后,以后再怎么滑動覆醇,cell都不會被創(chuàng)建了朵纷。也就是說本tableView要完整的工作,一共創(chuàng)建了12個cell永脓。
開始解釋原因了:
第一頁的界面一共需要展示8個cell袍辞,故而cell需要創(chuàng)建8次,每一個cell負(fù)責(zé)自己的數(shù)據(jù)顯示常摧。此8個創(chuàng)建以后搅吁,復(fù)用隊列依然為空(因?yàn)槟愦藭r還沒有滑動cell呢,復(fù)用隊列的元素不會增加)落午。然后在向下滑動顯示出第9個cell的時候似芝,還會調(diào)用cellForRowAtIndexPath方法,在此方法中板甘,它首先到可復(fù)用隊列中去找党瓮,由于此時隊列為空,它創(chuàng)建了一個cell盐类,打印日志寞奸,同時當(dāng)?shù)?個cell滑動出界面之外,第一個cell進(jìn)入到復(fù)用隊列中在跳,隊列中有一個元素枪萄,此元素的表示符為@"Default Style"。然后繼續(xù)向下滑動cell猫妙,開始顯示第10個cell瓷翻,它同樣到復(fù)用隊列中去找,第10個cell的標(biāo)示符為@"Subtitle Style"割坠,但是隊列中唯一的cell的標(biāo)示符為@"Default Style"齐帚,根據(jù)標(biāo)示符尋找,沒有找到彼哼,故而再次創(chuàng)建一個新的cell对妄,同時將滑動出界面的第2個cell進(jìn)入復(fù)用隊列。此時復(fù)用隊列有兩個元素敢朱,標(biāo)示符為@"Default Style"剪菱,@"Subtitle Style"摩瞎。同樣的道理,滑動到第11個cell的時候孝常,第3個cell入隊旗们,第12個cell的時候,第4個cell入隊构灸。此時復(fù)用隊列的元素個數(shù)為四個上渴,標(biāo)示符分別為:@"Default Style",@"Subtitle Style"冻押,@"Value1 Style"驰贷,@"Value2 Style".然后繼續(xù)滑動cell盛嘿,當(dāng)滑動到第13個cell的時候洛巢,它的標(biāo)示符為@"Default Style",它到復(fù)用隊列中去找次兆,可以找到稿茉。故而,這個cell就不會被創(chuàng)建了芥炭,同理漓库,再次向下滑動,以下的所有cell都可以根據(jù)標(biāo)示符找到對應(yīng)的cell园蝠,不會有被創(chuàng)建的渺蒿。在向下滑動的過程中,滑動出去的cell會被入隊彪薛,不過只入隊創(chuàng)建了的cell茂装,也就是說最終隊列中會有12個cell。對于每次取對應(yīng)標(biāo)示符的元素善延,到底取的是哪一個少态?采用的什么策略?這個我不知道易遣,我通過打印查看的是在向下滑動的過程中彼妻,一直順著隊列找,隊列是一個循環(huán)隊列豆茫。向上滑動的時候侨歉,逆著隊列向上找,由于是循環(huán)隊列揩魂,一直在轉(zhuǎn)圈为肮。
如果你仔細(xì)看的話,你會發(fā)現(xiàn)第一個cell本來沒有圖片肤京,為什么一劃下去再次滑動(如果滑動的距離遠(yuǎn)颊艳,一次搞定茅特,如果滑動的距離近,多上下滑動幾次)上來又有圖片了呢棋枕?這個就要思考一個:第一個cell在滑出界面又劃入界面的時候白修,是從復(fù)用隊列拿到的。復(fù)用隊列有12個元素重斑,第1兵睛,5,9還第一個cell有相同的標(biāo)示符窥浪,第1個沒有圖片祖很,第5個和第9個有圖片。當(dāng)用戶復(fù)用的是第一個cell的時候漾脂,它是沒有圖片假颇,當(dāng)用戶復(fù)用第5,9個cell的時候骨稿,它是有圖片的笨鸡。因此,當(dāng)你上下滑動坦冠,查看第一個cell的時候形耗,你會看到它一會有圖片,一會沒有圖片辙浑。這個跟復(fù)用時候的隊列查找規(guī)則有關(guān)激涤。
實(shí)用篇:
說了那么多,全是關(guān)于原理的∨信唬現(xiàn)在說點(diǎn)實(shí)用的倦踢。如果你想在所有的cell中添加一個按鈕,你是應(yīng)該在if中添加佛玄,還是應(yīng)該在if之外添加呢硼一?毫無疑問,應(yīng)該在if中梦抢,如果你是在if的外面添加的般贼,那會導(dǎo)致,你在向下滑動cell的過程中奥吩,取出來的cell本來已經(jīng)帶有button了哼蛆,而你還在addSubview,按鈕越來越多∠己眨或者你可以采用在if外面添加腮介,前提是每次先cell remove掉其所有的子視圖。這樣太消耗cpu端衰,麻煩了叠洗。如果你想一行隔著一行有按鈕和沒有按鈕甘改,你該怎么做呢?稍微思考一下灭抑,這個可是兩種風(fēng)格的cell十艾,故而在滑出界面進(jìn)行重用的時候,它們應(yīng)該屬于不同的標(biāo)示符腾节。于是你在創(chuàng)建cell的時候忘嫉,應(yīng)該去指定兩種標(biāo)示符,創(chuàng)建兩種cell案腺。當(dāng)然庆冕,也許你聰明了,我是不是可以在if之外先remove掉cell的所有子視圖劈榨,然后根據(jù)row % 2 == 0或者访递!=0 來進(jìn)行addSubView:button嗎?答案當(dāng)然是肯定的鞋既,但是這樣還是同樣的問題力九,太消耗cpu了耍铜。平常我們給每一個cell添加了一個button邑闺,肯定要添加事件的。對于不同的button棕兼,響應(yīng)不同的事件陡舅?那么我是不是通過在if語句中給button設(shè)置它的tag標(biāo)記(例如button.tag = indexpath.row)來實(shí)現(xiàn)呢?哈哈伴挚,你應(yīng)該足夠聰明了吧靶衍,當(dāng)然不行。你可以這樣想茎芋,if語句是用來創(chuàng)建的颅眶,它只被執(zhí)行了(例如上面的例子:12次),但是你可能有幾百行的cell田弥,當(dāng)然你的tag也就只有12個了涛酗,明顯不對應(yīng)。像這樣的偷厦,應(yīng)該怎么處理呢商叹?答案是:放在if的外面。你在if外面設(shè)置了tag標(biāo)記只泼,當(dāng)然剖笙,在某一個具體的時間點(diǎn)上,仍然只有12個標(biāo)記请唱,但是這12個標(biāo)記是可變的弥咪,例如當(dāng)前界面顯示第100-111號的cell过蹂,那么此時的button的tag就會是100-111了,仍然是12個按鈕聚至,但是它們會根據(jù)用戶的滑動榴啸,進(jìn)行不同的tag切換,相當(dāng)于擁有了很多個按鈕晚岭。如果你沒有被我說的話給弄暈鸥印,腦袋又足夠清醒的話,你應(yīng)該可以得出以下的結(jié)論:對于界面的定制坦报,放在if中比較好库说,一個cell中只創(chuàng)建一次;對于數(shù)據(jù)的定制片择,放在if外面比較好潜的,對于不同的cell,表示不同的內(nèi)容字管,雖然只有12個cell啰挪,但是cell中存放的數(shù)據(jù)我可以任意的映射。如果你得出了這個結(jié)論嘲叔,那么如果在加上textField,label等等亡呵,你應(yīng)該可以輕松搞定。不僅僅是表面上硫戈,更重要的是锰什,你理解了原理,掌握了機(jī)制丁逝,萬變都不怕汁胆,即使有新的需求,腦袋想想霜幼,或者拿著這篇文章看看嫩码,希望能給你一些啟示。
作者:lipeng08