前言:作為一個(gè)iOS開發(fā)者,tableView一定是我們最常用到的一個(gè)視圖,它分為表頭(tableHeaderView)亏娜、表尾(tableFooterView)、區(qū)頭蹬挺、區(qū)尾和單元格五個(gè)部分組成维贺。其中區(qū)頭區(qū)尾的重用個(gè)人感覺理解不夠透徹,暫且不談巴帮,我只給大家講解一下我對(duì)單元格重用的理解溯泣。
概述:tableView通過重用單元格來達(dá)到節(jié)省內(nèi)存的目的:通過為每個(gè)單元格指定一個(gè)重用標(biāo)識(shí)符(Identifier),即指定了單元格的種類,以及當(dāng)單元格滾出屏幕時(shí),允許恢復(fù)單元格以便重用.對(duì)于不同種類的單元格使用不同的重用標(biāo)示符,對(duì)于簡單的表格,一個(gè)重用標(biāo)識(shí)符就夠了。通俗點(diǎn)說榕茧,tableView里面的單元格的數(shù)據(jù)過多時(shí)垃沦,如果我們每次都不停的初始化單元格,這樣會(huì)消耗很多的資源用押,直觀的感受就是滑動(dòng)單元格時(shí)界面會(huì)卡頓肢簿。tableView需要顯示的單元格終究是有限的,如果合理的利用資源這才是重用最大的價(jià)值。一般來說tableView只會(huì)創(chuàng)建屏幕所能顯示的單元格數(shù)量加一個(gè)译仗,每當(dāng)我們滑動(dòng)是就會(huì)把消失在屏幕中的單元格放到重用池(重用隊(duì)列)抬虽,然后即將展示的部分就會(huì)從重用池里面根據(jù)重用標(biāo)示符去尋找單元格,如果從重用池里面找到了可以重用的單元格就直接拿來使用纵菌,沒有找到可以重用的那就重新初始化一下獲取新的單元格阐污,單元格重用從來就不是問題,問題是我們?nèi)绾伟堰@些重用的單元格處理后看起來是不同的咱圆,你可以理解為我們事實(shí)上是在重用笛辟,但是通過數(shù)據(jù)源不同從而顯示的不同,而重用的關(guān)鍵就是通過重用標(biāo)識(shí)符去重用池里面去尋找可以重用的單元格序苏。(PS重點(diǎn):數(shù)據(jù)源和重用標(biāo)識(shí)符)
舉個(gè)栗子
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
if (!cell)
{
1. cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"UITableViewCell"];
}
cell.textLabel.text = @"text";
2. [tableView registerNib:[UINib nibWithNibName:@"EvaluateHopsitalCell" bundle:nil] forCellReuseIdentifier:@"EvaluateCell"];
EvaluateHopsitalCell * cell = [tableView dequeueReusableCellWithIdentifier:@"EvaluateCell" forIndexPath:indexPath];
cell.nameLabel.text = @"name";
return cell;
}```
正文:不管是初始化還是注冊(cè)它們的核心原理都是一樣的手幢,就是在初始化的時(shí)候用來加載所有的界面,針對(duì)第一種情況忱详,為什么我們把添加子控件 if (!cell) 這個(gè)判斷條件之外的時(shí)候會(huì)重復(fù)添加并顯示围来,這是因?yàn)閱卧裢际菑闹赜贸乩锩婺脕淼模@些控件早已存在匈睁,但我們?cè)谥赜眠@些單元格上依舊添加控件监透,最后一定是會(huì)顯示控件重復(fù)添加,而且伴隨著不斷的滑動(dòng)界面會(huì)不停的重復(fù)添加控件航唆。注冊(cè)的單元格其實(shí)也是一樣的胀蛮,如果是xib則是在Cell 的 awakeFromNib還有xib里面初始化,如果注冊(cè)的是非xib的則是在對(duì)應(yīng)的初始化方法里糯钙,我們都是在這里添加各種不同的控件和約束粪狼,但是很多人采用的方法是不停的初始化單元格,又或者是不停的刪除子空間和添加子控件的方法來達(dá)到目的任岸,如果是這樣那你滑動(dòng)的時(shí)候卡頓的問題就永遠(yuǎn)解決不了再榄,因?yàn)槟氵@樣做無疑于廢棄了重用機(jī)制,這不是我們最終目標(biāo)享潜。我們一定要在初始化的處理好界面不跟,在重用時(shí)通過indexPath從數(shù)據(jù)源里面取對(duì)應(yīng)的對(duì)象,根據(jù)不同的數(shù)據(jù)和條件賦值才是最關(guān)鍵的米碰,即便單元格是重復(fù)使用的,可是數(shù)據(jù)是不同的购城,最后展示給用戶看到的是不同的界面吕座。那么又有人會(huì)說了,那界面不同的部分該如何處理瘪板,這個(gè)一般都是通過不同的條件判斷來 展示/隱藏 控件以及修改控件約束大小來實(shí)現(xiàn)不同的需求吴趴。當(dāng)然控制好數(shù)據(jù)源也是很重要的,即便數(shù)據(jù)不是包含對(duì)象的數(shù)組侮攀,也可以通過延展把數(shù)據(jù)轉(zhuǎn)化Model的方法變成自己做需要的數(shù)據(jù)源锣枝,總之我們要盡最大可能的用一個(gè)cell來展示所有的界面厢拭。(PS重點(diǎn):初始化負(fù)責(zé)界面,重用時(shí)通過數(shù)組和indexPath獲取數(shù)據(jù)和微調(diào)界面)
題外話撇叁,tableView里面重用的不單單是cell,還有去區(qū)頭和區(qū)尾供鸠,它們的原理性的知識(shí)都是一致的,但是在一些細(xì)節(jié)性的地方是不同的陨闹。如果對(duì)tableView的區(qū)頭和區(qū)尾重用不理解的話可以參考下collectionView的區(qū)頭和區(qū)尾楞捂,它們是比較相似的,tableHeaderView和tableFooterView是不重用的趋厉,而且我們每一次刷新一個(gè)去就會(huì)同時(shí)刷新它的區(qū)頭和區(qū)尾寨闹。