2013-02-27 84 views
3

似乎有很多關於此問題的問題,但我無法使用任何人的答案,所以希望有人可以回顧一下我是如何做到這一點的。我正在嘗試使用。我有兩個自定義的UITableViewCells,它們現在對它們只有一個BOOL屬性,這就是它的樣式。自定義UITableViewCells沒有在UITableView上重複使用

在我的cellForRowAtIndexPath方法基於什麼類型的數據回來我正在設計我的細胞。如果數據是「月」標題,那麼它就是一個看起來很長的細胞,如果它是「新聞」,它將成爲一個更大的白色細胞。

enter image description here

當表加載一切看起來很大,但如果我向下滾動,以創造更多的細胞,達到細胞被重建,並最終滾動減慢,因爲我跑出來的內存中,然後向後滾動。

當我設置中斷點時dequeueReusableCellWithIdentifier總是返回零,所以我的細胞不會重用,這似乎是一個問題。

在這張圖片中可以看到,細胞越來越堆疊在彼此的頂部和搞砸:

enter image description here

這裏我我的代碼:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *NewsCellIdentifer = @"NewsCellIdentifier"; 
    static NSString *MonthCellIdentifier = @"MonthCellIdentifier"; 


    NSUInteger row = [indexPath row]; 
    NewsItem *item = [self.newsArray objectAtIndex:row]; 

    if (item.IsMonth == YES) 
    { 
     NewsMonthUITableViewCell *cell = [self.mytableView dequeueReusableCellWithIdentifier:MonthCellIdentifier]; 

     if (cell == nil) 
     { 
      cell = [[NewsMonthUITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MonthCellIdentifier]; 
     } 

     // This handles any other "date" cells to allow for different spacing styles. 
     if (item.IsMonth) 
     { 
      UIImageView *av = [[UIImageView alloc] initWithFrame:CGRectMake(0, 10, 400, 20)]; 
      av.backgroundColor = [UIColor clearColor]; 
      av.opaque = NO; 
      av.image = [UIImage imageNamed:@"month-bar-bkgd.png"]; 
      UILabel *monthTextLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 150, 20)];; 
      CGFloat font = 11.0f; 
      monthTextLabel.font = [BVFont HelveticaNeue:&font]; 
      monthTextLabel.backgroundColor = [UIColor clearColor]; 
      monthTextLabel.font = [BVFont HelveticaNeue:&font]; 
      monthTextLabel.textColor = [BVFont WebGrey]; 
      monthTextLabel.text = item.Title; 

      cell.backgroundColor = [UIColor clearColor]; 
      [cell.contentView addSubview:av]; 
      [cell.contentView addSubview:monthTextLabel]; 
     } 

     return cell; 

    } 
    else 
    { 
     NewsUITableViewCell *cell = [self.mytableView dequeueReusableCellWithIdentifier:NewsCellIdentifer]; 

     if (cell == nil) 
     { 
      cell = [[NewsUITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NewsCellIdentifer]; 
     } 

     cell.contentView.backgroundColor = [UIColor clearColor]; 

     UIView *whiteRoundedCornerView = [[UIView alloc] initWithFrame:CGRectMake(10,10,300,100)]; 
     whiteRoundedCornerView.backgroundColor = [UIColor whiteColor]; 
     whiteRoundedCornerView.layer.masksToBounds = NO; 
     whiteRoundedCornerView.layer.cornerRadius = 3.0; 
     whiteRoundedCornerView.layer.shadowOffset = CGSizeMake(-1, 1); 
     whiteRoundedCornerView.layer.shadowOpacity = 0.5; 

     [cell.contentView addSubview:whiteRoundedCornerView]; 
     [cell.contentView sendSubviewToBack:whiteRoundedCornerView]; 
     [cell.contentView addSubview:[self NewsItemThumbnailView:item]]; 
     [cell.contentView addSubview:[self NewsItemTextView:item]]; 
     [cell.contentView addSubview:[self NewsItemCornerIconIndicatorView:item]]; 

     return cell; 

    } 

    return nil; 

} 

感謝您的任何援助或諮詢!

+0

你在使用故事板嗎? – 2013-02-27 16:55:11

+1

您是否正在使用動態原型的故事板?如果是,請檢查屬性檢查器中的每個單元格「標識符」是否設置正確。另外,如果你不使用故事板和動態原型,你創建和添加子視圖的代碼應該放在你的if(cell == nil)塊中。我的建議是使用動態原型的Storyboard並在IB中的單元格中進行自定義。 – 2013-02-27 16:57:13

+0

我正在使用Storyboard,但我沒有使用Prototyped單元格或在故事板中設計我的單元格。我只是將我的TableView放在屏幕上,但以編程方式完成剩下的工作。 – Flea 2013-02-27 16:57:36

回答

2

因爲你沒有動態原型使用故事板,那麼你需要將你的代碼創建並添加子視圖在你的if (cell==nil)塊中,否則所有的子視圖會在每次tableview單元被重新使用時再次被添加。

繼續前行,我的建議是使用動態原型的Storyboard(帶有子類UITableViewCells),並執行在IB中的單元格中定製

1

將您的單元格轉換爲Customcells,並使用tableView查看下面的示例。

NewsMonthUITableViewCell *cell = (NewsMonthUITableViewCell *)[tableView dequeueReusableCellWithIdentifier:MonthCellIdentifier]; 
    NewsUITableViewCell *cell =(NewsUITableViewCell*) [tableView dequeueReusableCellWithIdentifier:NewsCellIdentifer]; 

使用動態原型細胞,細胞的原型是有小區分配中沒有要求&檢查是否正確cellIdentifier。

在故事板上創建兩個原型單元&給他們不同的cellIdentifier,在你的情況下NewsCellIdentifer & MonthCellIdentifier。請確保NewsCellIdentifer的拼寫正確,因爲您錯過了NewsCellIdentifer的i

+0

Ravindra,謝謝你的迴應。我只是嘗試過,但仍然有相同的行爲。 – Flea 2013-02-27 17:00:17

+0

從桌面刪除自我查看 – 2013-02-27 17:03:19

+0

我認爲它是因爲self.myTableView,刪除它並只使用tableView – 2013-02-27 17:05:25

1

有趣的問題。你說你的信元出隊返回零。這是否被斷點或日誌證實?或者這僅僅是你發佈的圖片的扣除?

在我看來,可能會有另一個元兇堆疊在一起而不被重用的問題的罪魁禍首。

我可以看到,每次滾動單元格時,都會創建whiteRoundedCornerView並將其添加到單元格中。即使這不是你的問題的原因,這肯定是一個問題。你沒有正確地創建單元格。您必須將此代碼放入if(cell == nil)塊中。事實上,幾乎所有位於塊外的代碼都需要進入它。然後任何設置文本或圖像值的代碼都應該出現在塊之外。我看到有人已經提出了這個建議,但它並沒有讓你滿意。我只是再次強調它仍然是錯誤的,如果你想修復你的應用程序,你需要解決這個問題。 (順便說一下漂亮的應用程序)。

此外,如果我可以就你的代碼的其他方面提出建議。您自定義編碼的標題,並沒有使用實際的部分標題。這對我來說是非常奇怪的。另外,你有一個冗餘的「if(item。因爲一個已經在另一個塊中,它總是一個月的項目

+0

順便說一句,如果我的帖子不清楚,whiteRoundedCornerView的堆疊是什麼導致你在屏幕截圖中顯示的視覺工件。 – 2013-02-27 17:35:38

+0

我iPhone上的愚蠢刷新讓我錯過了這個已經爲你工作的事實。而是寫了這個長時間的迴應。 – 2013-02-27 17:38:19

+0

感謝eddieios,你是正確的,我需要把代碼放在(cell == nil)塊中!感謝您抽出寶貴時間回答,我將您的答案提高爲有用! – Flea 2013-02-28 19:25:32

0

我在iOS 7和storyboard上有同樣的問題,而我從來沒有在老版本的Xcode-SDK版本上使用相同的代碼出現此問題,而tr從stackoverflow許多建議,我無法修復它,並猜測什麼?!蘋果的TableView Programming Guide有很好的解釋指南。 甚至不需要使用cell==nil

所以我把這裏的指示,希望它可以幫助別人:

若要使用故事板將被重複使用得當,可以採取兩種不同的approacesh定製的tableview細胞。我個人更喜歡第一個更直接的,但我把這兩個解決方案放在這裏。

第一種方法

  1. 創建一個使用主從應用模板的項目,並選擇使用故事板選項。
  2. 在故事板畫布上,選擇主視圖控制器。
  3. 在Identity檢查器中,驗證Class是否設置爲自定義MasterViewController類。
  4. 選擇主視圖控制器內部的表格視圖。
  5. 在屬性檢查器中,驗證內容彈出式菜單是否設置爲動態原型。
  6. 選擇原型單元格。
  7. 在屬性檢查器中,在樣式彈出菜單中選擇自定義。
  8. 在標識符文本字段中輸入重用標識符。 這是與發送到dequeueReusableCellWithIdentifier:消息中的表視圖相同的重用標識符。
  9. 在Accessory彈出菜單中選擇Disclosure Indicator。
  10. 將庫中的對象拖動到單元格上。 對於此示例,拖動兩個標籤對象並將它們放在靠近單元格末端的位置(爲附件視圖留出空間)。
  11. 選擇對象並設置其屬性,大小和自動修改特徵。

爲此過程的編程部分設置的一個重要屬性是每個對象的tag屬性。在Attributes inspectorView部分中查找此屬性,併爲每個對象分配一個唯一的整數。

現在編寫您通常會寫入的代碼以獲取表視圖的數據。 (在這個例子中,你需要的唯一數據就是每個單元格的行號。)實現數據源方法的tableView:的cellForRowAtIndexPath:創建從原型一個新的細胞,並用數據填充它,在類似這樣的代碼的方式:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"]; 

    UILabel *label; 

    label = (UILabel *)[cell viewWithTag:1]; 
    label.text = [NSString stringWithFormat:@"%d", indexPath.row]; 

    label = (UILabel *)[cell viewWithTag:2]; 
    label.text = [NSString stringWithFormat:@"%d", NUMBER_OF_ROWS - indexPath.row]; 

    return cell; 
} 

有此代碼需要注意的幾個方面:

  • 您分配給原型單元格的字符串標識符是您傳遞給dequeueReusableCellWithIdentifier:中的表格視圖的字符串。
  • 因爲原型單元格是在故事板中定義的,所以dequeueReusableCellWithIdentifier:方法總是返回一個有效的單元格。您無需檢查返回值nil並手動創建單元格。
  • 代碼通過調用viewWithTag:傳入其標籤整數來獲取單元中的標籤。然後它可以設置標籤的文本內容。

第二種方法

如果你不喜歡使用標籤,您可以使用另一種方法設置單元格中的內容。爲要設置的對象定義一個帶有插座屬性的自定義UITableViewCell子類。在故事板中,將新類與原型單元相關聯,並將出口連接到單元中的相應對象。

要使用網點的自定義單元格內容

  1. 名爲MyTableViewCell的Objective-C類添加到您的項目。
  2. 下面的代碼添加到所述接口中MyTableViewCell.h

    @interface MyTableViewCell:的UITableViewCell

    @屬性(非原子,弱)IBOutlet中的UILabel * firstLabel; @property(非原子,弱)IBOutlet UILabel * secondLabel; @end

  3. 下面的代碼添加到實施MyTableViewCell.m

    @synthesize firstLabel,secondLabel;

  4. 下面的代碼行添加到實現該數據源的源文件:

    #進口「MyTableViewCell.h」

  5. 使用Identity inspector原型細胞的類設置爲MyTableViewCell

  6. 使用Connections檢查器將原型單元中的兩個出口連接到它們對應的標籤。 enter image description here

  7. 實現數據源的方法tableView:cellForRowAtIndexPath:

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"]; 
    
    cell.firstLabel.text = [NSString stringWithFormat:@"%d", indexPath.row]; 
    cell.secondLabel.text = [NSString stringWithFormat:@"%d", NUMBER_OF_ROWS - indexPath.row]; 
    
    return cell; 
    } 
    

該代碼能夠訪問到標籤在使用細胞的存取方法(點表示法用在這裏)。代碼然後可以設置標籤的文本內容。

相關問題