2012-02-14 72 views
8

我有一個tableView的部分,可以打開和關閉。所以,當我點擊某個部分打開它時,它會被填滿單元格,並且-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)的調用次數與我在-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section中提供的次數完全相同。tableView:cellForRowAtIndexPath:不僅爲可見細胞調用?

這是正確的嗎?它不應該只是可見細胞的數量嗎?

因爲在我的情況下我有不好的情況:我有很多自定義單元格(50〜100個單元格),並且爲每個單元格調用-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)會減慢部分的打開速度,導致每次從nib讀取都執行,內容正在填充圖像。 我有細胞的檢查知名度內-(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; 
} 

是否仍然正確?或者我錯過了什麼?

回答

5

嗯,我以某種方式處理了我的問題。這是我的想法和想法,我是如何找到解決方案的。也許這可能對某人有所幫助。

我已經指示內存分配和調用堆棧使用儀器在開幕式的事件。它告訴我,大部分時間都花在從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; 
} 

正如你所看到的,我不是隻用-(NSArray*)indexPathsForVisibleRows的tableview的方法檢測可見單元格。相反,我寫了我自己的方法-(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; 
} 

,我已經減少了與大量定製的細胞,這是由儀器追蹤和證明的開口部分的時間在體驗應用時感受到了。

+0

這真棒,我也有這樣的問題,你的技術是如此有用,問題得到解決。 – Ananth 2013-06-11 09:39:42

+0

@Ananth歡迎您! =) – peetonn 2013-06-12 11:44:42

0

這似乎是正確的。關於優化加載本身的想法在於「dequeueReusableCellWithIdentifier」的工作方式。 如果你從遠程位置加載圖像,這是你想要優化代碼的地方。但不是來自單元格的加載,因爲這看起來正確。

+0

這聽起來很傷感。我暫時關閉了使用圖像填充單元格的細節,與僅有9個單元格的部分相比,用42個單元格打開部分的延遲仍然很小。我認爲這是唯一的方法 - 減小自定義單元的尺寸,並減少其中使用的uiviews的數量。你怎麼想? – peetonn 2012-02-15 00:50:03

+0

我很好奇你是如何展開/摺疊UITableView中的部分。因爲這不是默認的。 – 2012-02-15 01:13:21

+0

使用'insertRowsAtIndexPaths:withRowAnimation:'和'deleteRowsAtIndexPaths:withRowAnimation:' – peetonn 2012-02-15 01:19:14

0

我使用了一些相似的技術,但由於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; 
} 

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

0

添加一個別人解決了我的問題。 我在哪裏重置了對單元格所做的任何更改。

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

} 
2

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

+2

當我知道我所有的單元格的高度> 320pts時,我將tableView的estimatedRowHeight值設置爲100pts的低值。這導致額外的細胞不必要的加載,直到100 + 100 + ...> tableView可見邊界。然後我將estimatedRowHeight更改爲320,並且加載的行數減少了。 – SayeedHussain 2016-07-23 09:32:15

相關問題