iOS - UITableView中Cell重用機制導致Cell內容出錯的解決辦法


  "UITableView" iOS開發中重量級的控件之一;在日常開發中我們大多數會選擇自定Cell來滿足自己開發中的需求, 但是有些時候Cell也是可以不自定義的(比如某一個簡單的頁面,只需要展示一些簡單的信息);但是當頁面大於屏幕顯示的范圍的時候, 滑動UITableView的時候,Cell上的內容會出現混亂或者錯誤的現象,經過反復的查找問題應該是出現在UITableViewCell的重用機制上;那么下面我們就來說一下解決這種問題的幾種辦法,以及最好的解決辦法:

(一)使用系統的Cell,簡單的Cell重用機制我們會這樣去寫:

 1 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 2     static NSString *cellIdentifier = @"cellID";
 3     
 4     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
 5     
 6     if (!cell) {
 7         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier];
 8     }
 9     
10     // 說明: 要測試Cell內容是否錯亂, 要將每行Cell顯示的內容不同, 才能看出來
11     cell.textLabel.text = @"Cell顯示內容";
12     cell.detailTextLabel.text = @"Cell輔助顯示內容";
13     
14     return cell;
15 }

  這樣寫雖然達到了Cell的重用, 但是會出現我們要討論的話題(滑動UITableView出現Cell內容混亂的情況),那么下面我們就來說一下避免Cell內容出現混亂的寫法;

 

(二)使用系統的Cell,避免Cell內容出現混亂的寫法:

  (1)方法一:

    ①將獲得Cell的方法:- (UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier; 換為:- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath;

    ②解決了Cell內容混亂的現象,但是沒有能夠達到Cell的重用機制的原理;因為cellForRowAtIndexPath(只從要更新的cell的那一行取出cell),不使用重用機制,因而問題就可以得到解決,但是會浪費一些空間(真機測試比其他方法略顯卡頓);

    ③示例代碼:

 1 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 2     static NSString *cellIdentifier = @"cellID";
 3     
 4     // UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
 5     // 將上面的方法換成(根據indexPath准確地取出一行, 而不是從cell重用隊列中取出, 方法如下:)
 6     UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
 7     
 8     if (!cell) {
 9         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier];
10     }
11     
12     // 說明: 要測試Cell內容是否錯亂, 要將每行Cell顯示的內容不同, 才能看出來
13     cell.textLabel.text = @"Cell顯示內容";
14     cell.detailTextLabel.text = @"Cell輔助顯示內容";
15     
16     return cell;
17 }

  (2)方法二:

    ①通過為每個cell指定不同的重用標識符(reuseIdentifier)來解決;

    ②重用機制是根據相同的標識符來重用Cell的,標識符不同的Cell不能彼此重用;我們將每個Cell的標識符都設置為不同,就可以避免不同Cell重用的問題了;

    ③示例代碼:

 1 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 2     // static NSString *cellIdentifier = @"cellID";
 3     // 將上面的方法換成(以indexPath來唯一確定Cell, 方法如下:)
 4     NSString *cellIdentifier = [NSString stringWithFormat:@"Cell%zd%zd", [indexPath section], [indexPath row]];
 5     
 6     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
 7     
 8     if (!cell) {
 9         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier];
10     }
11     
12     // 說明: 要測試Cell內容是否錯亂, 要將每行Cell顯示的內容不同, 才能看出來
13     cell.textLabel.text = @"Cell顯示內容";
14     cell.detailTextLabel.text = @"Cell輔助顯示內容";
15     
16     return cell;
17 }

  (3)方法三:

    ①通過刪除重用的Cell的所有子視圖,從而得到一個沒有特殊格式的Cell,供其他Cell重用;

    ②示例代碼:

 1 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 2     static NSString *cellIdentifier = @"cellID";
 3     
 4     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
 5     
 6     if (!cell) {
 7         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier];
 8     } else {
 9         // 刪除Cell的所有子視圖
10         while ([cell.contentView.subviews lastObject] != nil) {
11             [(UIView*)[cell.contentView.subviews lastObject] removeFromSuperview];
12         }
13     }
14     
15     // 說明: 要測試Cell內容是否錯亂, 要將每行Cell顯示的內容不同, 才能看出來
16     cell.textLabel.text = @"Cell顯示內容";
17     cell.detailTextLabel.text = @"Cell輔助顯示內容";
18     
19     return cell;
20 }

  (以上便是對相關知識的相關介紹和理解,還希望大家相互補充共同進步)


免責聲明!

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



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