ios基礎之UITableViewCell的重用(帶示例原創)


之前一個月剛剛系統的開始接觸IOS開發,對UI控件大體了解了一遍,但是因為沒有實際的參與項目,對細枝末節的還是不很清楚。

昨天突然想到:UITableViewCell的重用到底是怎么回事,上網查了許多資料后略有體會,但大都差不多,於是想自己實驗一下。

便新建了個single view的工程,在storyboard上拖了個tableview,用最基礎的方法綁定了cell,並用了重用。

 1 -(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 2 {
 3     //為表格行定義一個靜態字符串作為標示
 4     static NSString *cellID = @"cellId";
 5     NSLog(@"hanghao:%ld",(long)indexPath.row);
 6     //從可重用的表格行的隊列中取出一個表格行
 7     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
 8     if (cell == nil) {
 9         NSLog(@"重新創建對象");
10         switch (indexPath.row % 4) {
11             case 0:
12                 //使用UITableViewCell創建普通單元格,使用自定義的LYCTableViewCell創建自定義單元格
13                 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID];
14                 break;
15             case 1:
16                 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
17                 break;
18             case 2:
19                 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellID];
20                 break;
21             case 3:
22                 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:cellID];
23                 break;
24             default:
25                 break;
26         }
27     }
28     //單元格設為圓角
29     cell.layer.cornerRadius = 12;
30     cell.layer.masksToBounds = YES;
31     
32     //獲取當前的行號
33     NSUInteger rowNo = indexPath.row;
34     cell.textLabel.text = [books objectAtIndex:rowNo];
35     //為uitableviewcell左端設置圖片
36     cell.imageView.image = [UIImage imageNamed:@"123.png"];
37     //設置左端高亮圖片
38     cell.imageView.highlightedImage = [UIImage imageNamed:@"123_h.png"];
39     
40     cell.detailTextLabel.text = [details objectAtIndex:rowNo];
41     return cell;
42 }

說實話,剛開始接觸的時候真不知道 dequeueReusableCellWithIdentifier  這是個什么東西,后來在網上搜索的時候說這是根據id查找可重用的cell,但是說的太籠統了,到底什么算是可重用cell?

如果這個table中有多個自定義類型的cell,該怎么重用,這個問題糾結了一下午,到晚上睡覺前終於想通了。

先說簡單的情況,當我們的tableview種的cell為單一類型,而且cell的高度是一個統一的高度,即顯示一個這樣的列表:

例如上圖,那么在 -(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

方法中,if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cID];
    }

這幾行代碼將被執行11次,也就是創建11個指向不同地址的cell。

為什么是11次?因為當前window中顯示了11個cell,雖然最后一個只顯示了一半。(如果在iphone 6 plus中,創建的cell肯定大於11個,因為屏幕比5s的大)

這是在靜止時候創建的cell。

那么當我們滑動屏幕的時候,有會發生或者觸發哪些操作呢?

上面的圖中,為將tableview向上滑動了一點,出現了一個新的cell(android高級),這個時候,系統會在創建一個新的cell對象,此時的內存中會有12個cell的對象。

當我們繼續向上滑動,當[C#高級編程]對應的那個cell消失在tableview的可視區域的時候,那個cell將被tableview放到他的重用列表中。

而新出現的cell將會重用重用列表中的那個cell,只是對cell中的文本重新賦值而已,

這樣一直循環:當用戶滾動tableview時,如果cell不可見,將被扔進可重用列表,在其他行即將顯示在tableview中時,重用那個cell,重新復制,以達到節省內存的效果。

按照上面的例子,那么內存中最多會創建12個cell,即使你的datasource中有1000條數據,也還是12個cell對象在內存中,只是tableview替我們控制了顯示隱藏時重用cell。

如果我們不在編程時使用重用機制,那么可想而知,創建1000個甚至10000個cell在內存中,是多么浪費。

 

上面講了單一種類cell的現實,那么多種cell是怎么顯示的呢,其實只要上面的思路清晰了,那么多種cell也是同樣的道理。

先上一下源代碼

 1 #pragma mark - Table view data source
 2 
 3 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
 4     // Return the number of sections.
 5     return 4;
 6 }
 7 
 8 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
 9     // Return the number of rows in the section.
10     NSLog(@"rowNumber");
11     if (section % 2 == 0) {
12         return 1;
13     }
14     return 30;
15 }
16 
17 
18 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
19     static NSString *defaultCellID = @"default";
20     static NSString *firstCellID = @"first";
21     
22     //注冊可重用cell
23     if (!_isRegistNib) {
24         NSLog(@"registernib");
25         UINib *nib = [UINib nibWithNibName:@"CustomTableCellDefaultView" bundle:nil];
26         [tableView registerNib:nib forCellReuseIdentifier:defaultCellID];
27         
28         UINib *nibFirst = [UINib nibWithNibName:@"HomeTableCellFirstView" bundle:nil];
29         [tableView registerNib:nibFirst forCellReuseIdentifier:firstCellID];
30         _isRegistNib = !_isRegistNib;
31     }
32     NSInteger sectionIndex = indexPath.section;
33     
34     
35     if (sectionIndex % 2 == 0) {
36         //如果是第一個區域,顯示歡迎的cell
37         HomeTableCellFirst *cell = (HomeTableCellFirst *)[tableView dequeueReusableCellWithIdentifier:firstCellID forIndexPath:indexPath];
38         NSLog(@"創建第一個cell");
39         NSLog(@"cell的地址是:%@",cell);
40         NSLog(@"--------------------------------------");
41         return cell;
42     }
43     else if(sectionIndex % 2 == 1){
44         //如果是第二個區域,顯示普通的cell
45         CustomTableCellDefault *cell = (CustomTableCellDefault *)[tableView dequeueReusableCellWithIdentifier:defaultCellID forIndexPath:indexPath];
46         NSLog(@"創建普通的cell");
47         NSLog(@"cell的地址是:%@",cell);
48         NSLog(@"--------------------------------------");
49         cell.lblStoreName.text = [NSString stringWithFormat:@"店家%ld",(indexPath.row+1)];
50         return cell;
51     }
52     else{return nil;}
53     
54     
55     
56 }
57 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
58 {
59     if (indexPath.section % 2 == 0) {
60         return 150;
61     }
62     return 80;
63 }
64 
65 -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
66 {
67     return 10;
68 }

上面的tableview實在ib中拖進去的,style時group

在代碼中設置了section的數量是4,在- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

方法中,使用registerNib:forCellReuseIdentifier方法注冊了兩種自定義的cell,並且會打印cell的地址及其他信息,先來看下運行效果

 

剛打開view的時候,tableview一共加載了[cell1]一個,[cell2] 7個。

當我們繼續向上滾動的時候,因為當前[cell2]的數量並不能充滿整個window,所以還會繼續創建cell2的對象,與此同時,唯一的一個cell1消失在window的時候,被tableview扔進了重用列表。

通過上面的圖,看到nslog打印出來的cell指向的地址,很清楚,我們創建了7個不同的[cell2]對象

當繼續滾動的時候,會繼續打印出和上面地址不重復的[cell2],大家可以自己試試,我就不上圖了

因為我讓第三個section又顯示了[cell1],所以繼續向下滾動,當它出現時,控制台打印的cell的地址是0x7fbc2176c620,和第一個cell是同一個對象,因為使用了重用列表中的那個[cell1]的對象。

 

通過上面的實驗,可以總結下面的結論:

使用重用機制后:

1、tableview至少會創建可視區域高度cell高度 個 cell對象,因為當第一個cell隱藏了一半時,意味着要還要創建一個新的cell

2、創建了足夠多的cell后,再顯示cell就會使用可重用隊列中的cell

 

以上是本人自己的理解,如果不對的地方,還希望和大家多多交流。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM