2014-09-22 94 views
4

更新到iOS 8後,我的應用程序在UITableView中滾動時出現嚴重的性能問題 - 它在iOS 7上完全沒有。它似乎滯後或經常跳轉一點。iOS 8桌面視圖控制器性能問題

它會影響較舊的(第二代)和較新的(第四代視網膜)iPad,但不會影響iPhone,因爲我的iPhone 5可以通過以完全相同方式構建的TableView滾動。

重要:它似乎隻影響UITableViewControllers在形式片呈現模態 - 在默認UIViewController中手動創建別的地方不表意見。甚至沒有一個具有自定義表視圖的UIViewController表單(例如屬性)受到影響。

儀器說CPU時間大約3%轉到cellForRowAtIndex方法,這是最耗時的方法。這3%中,75%呈上行:

EventTableViewCell *cell = [tableView 
          dequeueReusableCellWithIdentifier:CellIdentifier 
          forIndexPath:indexPath]; 

cellForRowAtIndex看起來是這樣的:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    static NSString *CellIdentifier = @"tablecell"; 

    EventTableViewCell *cell = [tableView 
           dequeueReusableCellWithIdentifier:CellIdentifier 
           forIndexPath:indexPath]; 

    NSDictionary *thismsg = [messages objectAtIndex:indexPath.row]; 

    switch ([[thismsg objectForKey:@"type"] intValue]) { 
     case 1: 
     cell.eventTitleLabel.textColor = [UIColor greenColor]; 
      break; 
     case 2: 
     cell.eventTitleLabel.textColor = [UIColor redColor]; 
      break; 
     case 3: 
     cell.eventTitleLabel.textColor = [UIColor colorWithRed:0.0 green:128.0/255.0 blue:1.0 alpha:1]; 
      break; 
     case 4: 
      cell.eventTitleLabel.textColor = [UIColor orangeColor]; 
      break; 
     default: 
      cell.eventTitleLabel.textColor = [UIColor whiteColor]; 
      break; 

    } 
    cell.eventTitleLabel.text = [thismsg objectForKey:@"m"]; 
    cell.timestampLabel.text = [thismsg objectForKey:@"t"]; 
    cell.authorNameLabel.text = [thismsg objectForKey:@"a"]; 

    cell.backgroundColor = [UIColor blackColor]; // this needs to be here, but removing it makes no difference to performance. 
    return cell; 
} 

我的子類的細胞具有IB僅由幾個標籤,這是那些文字是分配給。

的視圖控制器和表視圖的故事板的設置是這樣的: enter image description here

EventTableViewCell.h:

屬性鏈接到上述圖像顯示故事板的元件

@interface EventTableViewCell : UITableViewCell 
@property (weak, nonatomic) IBOutlet UILabel *eventTitleLabel; 
@property (weak, nonatomic) IBOutlet UILabel *timestampLabel; 
@property (weak, nonatomic) IBOutlet UILabel *authorNameLabel; 

@end 

EventTableViewCell .m:

@implementation EventTableViewCell 

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 
{ 
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 
    if (self) { 
     // Initialization code 

    } 
    return self; 
} 

- (void)awakeFromNib 
{ 
    // commenting out this method does nothing to performance, only makes it the wrong color 
    UIView *bgColorView = [[UIView alloc] init]; 
    bgColorView.backgroundColor = [UIColor darkGrayColor]; 
    [self setSelectedBackgroundView:bgColorView]; 
} 

- (void)setSelected:(BOOL)selected animated:(BOOL)animated 
{ 
    [super setSelected:selected animated:animated]; 
    // Configure the view for the selected state 
} 


@end 

快速查看調試導航器在極端向上和向下滾動期間(您作爲普通用戶所做的任何事情都是如此)。正常的快速滾動會導致大約15%的CPU使用率。這些峯值在25%的標記 - 我假設,因爲他們運行在同一線程和iPad有4可用。快速滾動的性能與慢速滾動的性能相同,因此CPU似乎並未參與其是否滯後。這個0%是在我停止滾動截取屏幕截圖之後,表明該應用程序是而不是忙於在後臺或其他視圖控制器中執行其他任何操作。而且正如你所看到的,它也不會泄漏內存,因爲無論持續滾動多長時間,它都會持續下降到23MB左右。

enter image description here

+3

你有沒有嘗試分析應用程序? – Shai 2014-09-22 06:47:04

+2

你能否粘貼你的表格視圖的代碼 – meim 2014-09-22 07:08:11

+2

@nickdnk如果你想成爲一名認真的iOS開發人員學習使用Instruments。過去幾年中,我不得不優化許多表格視圖代碼。人們可以犯的錯誤太多了。儀器可以幫助你做到更多。 – dasdom 2014-09-22 09:47:18

回答

2

編輯:這一直在iOS 10中修復。我不知道原因是什麼,但更新設備到iOS 10的結果與iOS7相同 - 平滑滾動如預期。 編輯再次:此問題已返回10.1或10.2。仍然不知道發生了什麼事。

好的。經過數小時和數小時的分解我的應用程序,我發現原因。

事實證明,問題是由顯示視圖控制器而不是表視圖控制器本身造成的。

以下是我發現了,且症狀如何連接:

它不僅影響本地表視圖控制器,因爲這些都是由同一個問題的VC呈現。所有其他表格視圖在其他地方或在有問題的VC中呈現,由於某種原因,這些視圖沒問題。

它與cellForRow方法或用於呈現每個單元格的類無關。

呈現視圖控制器是一個全屏幕iPad視圖控制器與很多按鈕。這些按鈕分別代表房間中的一個物體,可以挖掘物業。這一直工作正常,直到iOS 8,這個線程開始。由於我不知道的原因,按鈕的0.7的alpha值使得任何呈現的Table View控制器的行爲都不正確。我通過爲呈現視圖控制器逐個挑選元素而發現。

我禁用了我的按鈕設置α,和一切工作的預期,因爲它沒有在iOS 7

我試圖與iOS 8谷歌的α相關的問題,但一無所獲行。

無論如何 - 問題解決了,儘管限制了我的按鈕不再透明。

2

即時反饋:

註冊筆尖和使用dequeueReusableCellWithIdentifier:forIndexPath:。當你獲取你的單元格時,你給表格視圖提供了更多信息,因此大大增加了良好緩存的機會。您也可以放棄您的if (cell == nil)條款。

這一點可能是最昂貴的部分:

UIView *bgColorView = [[UIView alloc] init]; 
bgColorView.backgroundColor = [UIColor darkGrayColor]; 
[cell setSelectedBackgroundView:bgColorView]; 

每一個觀點是支持層和每一層都有GPU足跡。所以你在CPU和GPU方面都會導致分配。 tableview的視圖重用的重點在於創建視圖是昂貴的。

要解決這個問題,如果你去NIB路線,或者至少只做一次,可能在EventTableViewCell -initWithStyle:之內。

相反,如果你想堅持使用純代碼的方法,下面應該工作:

// e.g. in viewDidLoad, assuming you have self.tableView; this tells the 
// tableview that the class EventTableViewCell is the thing that is used to 
// display any data with which you'd supply the reuse 
// identifier CellIdentifier 
[self.tableView registerClass:[EventTableViewCell class] 
     forCellReuseIdentifier:CellIdentifier]; 

... elsewhere ... 
-(UITableViewCell *) 
    tableView:(UITableView *)tableView 
    cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    EventTableViewCell *cell = [tableView 
      dequeueReusableCellWithIdentifier:CellIdentifier 
      forIndexPath:indexPath]; 

    // cell now definitely exists and is non-nil if EventTableViewCell 
    // is currently returning non-nil objects for 
    // initWithStyle:reuseIdentifier:; there's definitely no point calling 
    // that again, at least 

    NSDictionary *thismsg = [messages objectAtIndex:indexPath.row]; 
... etc ... 

當然,這些都只是我的直接反應。如果你還沒有運行Instruments,你甚至不知道瓶頸是否在你的tableview數據源中。只是把我的頭頂部,它只是爲可能EventTableViewCell可以做一些昂貴的東西,那別人可能會增加額外的手勢識別器,做自己的大處理任務等

+0

註釋掉整個塊沒有任何區別。我不明白第一部分?你不能刪除if零部分,因爲整個想法是檢查單元是否已經靜態創建。這是所有表視圖的默認值,並且是在您創建UITableViewController的新子類時Xcode自動生成的代碼。 – nickdnk 2014-09-22 18:48:06

+0

@nickdnk你在談論iOS 5及以下版本。檢查文檔。我引用:「在出列任何單元之前,調用此方法或registerNib:forCellReuseIdentifier:方法來告訴表視圖如何創建新單元。如果指定類型的單元當前不在重用隊列中,則表**視圖使用提供的信息自動創建一個新的單元格對象**「(強調添加)(哦,如果你喜歡,可以註冊一個類而不是NIB; NIB更容易,因爲你可以直接將它們包含在Storyboard中,如果你在那裏保持更新) – Tommy 2014-09-22 18:55:41

+0

好吧。你能發佈一個完整的例子嗎?我真的不知道什麼是筆尖。我只用過故事板,只是將我的TableViews,單元格等子類化了。編輯:我的意思是說出整個背景UIView - 添加沒有任何區別。 – nickdnk 2014-09-22 19:36:11