簡體   English   中英

tableView:cellForRowAtIndexPath:不僅為可見單元格調用?

[英]tableView: cellForRowAtIndexPath: get called not only for visible cells?

我有一個tableView與部分,可以打開和關閉。 因此,當我點擊一個部分打開它時,它正在充滿細胞和-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)被調用的次數與我提供的完全相同-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

那是對的嗎? 不應該只是可見細胞的數量?

因為在我的情況下我的情況很糟糕:我有很多自定義單元格(50~100個單元格)和調用-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)每個單元格的開放速度減慢一節,因為每次執行從筆尖讀取並且單元格內容正在填充圖像。 我檢查了單元格內部的可見性-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)如下所示:

if ([[self.tableView indexPathsForVisibleRows] containsObject:indexPath])
    NSLog(@"visible %@", indexPath);

並且它表明,在45個細胞中,只有6或7個可見。 其他人不在可見區域。 但創建細胞仍然執行。 這是代碼:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath    {
static NSString *CellIdentifier = @"IVCell";
IVCamera *camera = [server.cameras objectAtIndex:indexPath.row];

IVServerListViewCell *cell = (IVServerListViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    [[NSBundle mainBundle] loadNibNamed:@"IVServerListCell" owner:self options:nil];
    cell = (IVServerListViewCell*)_tableViewCell;
    self.tableViewCell = nil;

}

[cell textLabel].text = camera.cameraName;
cell.preview = camera.preview;
cell.userData = camera; 
cell.isEnabled = (server.isInactive)?NO:camera.isOnline;

return cell;
}

它還是正確的嗎? 或者我錯過了什么?

好吧,我不知何故處理了我的問題。 以下是我的想法和想法,我是如何找到解決方案的。 也許它對某人有幫助。

我在打開部分事件期間使用Instruments指示了內存分配和調用堆棧。 它告訴我,大部分時間花在從nib文件加載單元格上。

首先,我所做的是減少nib文件的大小 ,即最小化自定義tableview單元格中使用的視圖數量(現在只有2個視圖和2個標簽,而不是之前的6個視圖,2個圖像和2個標簽)。 它給了我一些細胞加載的改善。 Apple文檔建議盡可能少地使用視圖,不要使用透明度。 所以要注意這些建議。

其次,正如我之前發現的那樣,並非所有單元格都是可見的-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) ,我決定以某種方式減少從nib文件中加載新單元格的數量。 為了達到這個目的,我提出了一個簡單的想法:為不可見的行返回空白默認單元格,同時從nib加載自定義單元格以顯示可見行。 這是一段代碼:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([self index:indexPath isInvisibleInTableView:tableView])
        return [self getBlankCellForTableView:tableView];

    // the rest of the method is the same
    ...
}

-(BOOL)index:(NSIndexPath*)indexPath isInvisibleInTableView:(UITableView*)tableView
{
    NSMutableArray *visibleIndexPaths = [self getExtendedVisibleIndexPathsForTableView:tableView];

    return ![visibleIndexPaths containsObject:indexPath];
}

-(UITableViewCell*)getBlankCellForTableView:(UITableView*)tableView
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"IVBlankCell"];
    if (!cell)
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"IVBlankCell"] autorelease];

    return cell;
}

正如您所看到的,我不是只使用tableview的-(NSArray*)indexPathsForVisibleRows方法來檢測可見單元格。 相反,我已經編寫了自己的方法-(NSMutableArray*)getExtendedVisibleIndexPathsForTableView:(UITableView*)tableView 這是必要的,因為出於某種原因,當使用-(NSArray*)indexPathsForVisibleRows ,最后一個可見單元格旁邊的單元格或第一個可見單元格之前的單元格被創建為空白單元格,看起來像空單元格滾動。 為了解決這個問題,在-(NSMutableArray*)getExtendedVisibleIndexPathsForTableView: (UITableView*)tableView我將邊框單元格添加到可見數組單元格中:

-(NSMutableArray*)getExtendedVisibleIndexPathsForTableView:(UITableView*)tableView{
    NSArray *visibleIPs = [tableView indexPathsForVisibleRows];

    if (!visibleIPs || ![visibleIPs count])
        return [NSMutableArray array];

    NSIndexPath *firstVisibleIP = [visibleIPs objectAtIndex:0];
    NSIndexPath *lastVisibleIP = [visibleIPs objectAtIndex:[visibleIPs count]-1];

    NSIndexPath *prevIndex = ([firstVisibleIP row])?[NSIndexPath indexPathForRow:[firstVisibleIP row]-1  inSection:[firstVisibleIP section]]:nil;
    NSIndexPath *nextIndex = [NSIndexPath indexPathForRow:[lastVisibleIP row]+1 inSection:[lastVisibleIP section]];

    NSMutableArray *exVisibleIndexPaths = [NSMutableArray arrayWithArray:[tableView indexPathsForVisibleRows]];

    if (prevIndex)
        [exVisibleIndexPaths addObject:prevIndex];
    [exVisibleIndexPaths addObject:nextIndex];

    return exVisibleIndexPaths;
}

因此,我減少了打開具有大量自定義單元格的部分的時間,這在儀器跟蹤和體驗應用程序時感受到了。

檢查你的tableview大小。 可能是你的tableview高度非常大,它繼續加載單元格,直到你的單元格填充所有tableview大小..

增加你的

UITableview的估計值。

只需為UITableViewCell添加估計的高度

問題在我的情況下:cellforRowAtIndexPath被稱為array.count次,而顯示的單元格小於array.count。

要解決這個問題,我剛剛更換了,

  • (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

用,

  • (CGFloat)tableView:(UITableView)tableView estimatedHeightForRowAtIndexPath :( nonnull NSIndexPath)indexPath;

我使用了一些類似的技術,但由於indexPathsForVisibleRows已經排序,因此您不需要使用containsObject。 相反,你可以這樣做:

//
// Checks if indexPath is visible in current scroll state, we are expanding bounds by 1
// because the cells that are next to the last one visible or the cells that are previous
// to the first one visible could look empty while scrolling.
//
- (BOOL)isIndexPathVisible:(NSIndexPath *)indexPath
{
    NSInteger row = [indexPath row];
    NSArray *visible = [self.tableView indexPathsForVisibleRows];
    NSInteger count = [visible count];
    NSInteger first = (count > 0) ? MAX([visible[0] row] - 1, 0): 0;
    NSInteger last = (count > 1) ? [visible[1] row] + 1: first + 2;

    return row >= first && row <= last;
}

順便說說; 這假設您只使用一個部分。 它不適用於多個部分。

添加其他解決了我的問題。 我重置了對單元格所做的任何更改。

if (! self.cell) {
    self.cell = [[LanguageCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    self.cell.accessoryType = UITableViewCellAccessoryNone;
}
else
{
    self.cell.checkImage.image = NO;

}

這似乎是正確的。 優化加載本身的想法在於“dequeueReusableCellWithIdentifier”的工作原理。 如果您正在從遠程位置加載圖像,那么您可能希望優化代碼。 但不是來自細胞的加載,因為這看起來正確。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM