2012-07-05 85 views
0

我有一個顯示自定義單元格的表格視圖,這些單元格包含我從文檔文件夾加載的圖像。我注意到,當我滾動表格時,出現了一些滯後現象,我假設這是從加載磁盤映像來的。然而,圖像已經加載在這一點,所以我有點困惑。自定義表單元格滾動

關於優化此代碼的建議,將不勝感激。我已閱讀關於延遲加載,但我不知道這是否適用於我。

我確實檢查了一下,以確定表格正在重新使用單元格。

編輯:

- (void)configureCell:(BeerCell *)cell 
      atIndexPath:(NSIndexPath *)indexPath 
{ 
    Beer *beer = (Beer *) [self.fetchedResultsController objectAtIndexPath:indexPath]; 
    cell.displayBeerName.text = beer.name; 

    // check to see if there is a cached image already. Use a dictionary. 
    // make sure this is one of your ivars 
    __block UIImage *theImage = [self.imagesCache objectForKey: beer.imagePath]; 

    // If the image is not in your cache, you need to retrieve it. 
    if (!theImage){ 
     // The image doesn't exist, we need to load it from disk, web or render it 

     // First put a placeholder image in place. Shouldn't be any penalties after the 
     // first load because it is cached. 
     cell.beerImage.image = [UIImage imageNamed:@"beer-pic.png"]; 

     // check to see if your image cache dictionary has been created, if not do so now 
     if (_imagesCache == nil) { 
      _imagesCache= [[NSMutableDictionary alloc] initWithCapacity:1]; 
     } 

     // get a weak reference to UITableViewController subclass for use in the block 
     // we do this to avoid retain cycles 
     __weak BeerListViewController *weakSelf = self; 

     // do the heavy lifting on a background queue so the UI looks fast 
     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0); 
     dispatch_async(queue,^{ 

      theImage = [UIImage imageWithContentsOfFile:beer.imagePath]; 

      // I added this in because I create the new core data object in this class, and pass 
      // it to the class where I fill out the information about the beer 
      if (theImage) { 

       // Add the image to the cache 
       [weakSelf.imagesCache setObject:theImage forKey:beer.imagePath]; 
       //[weakSelf.imagesCache addObject:theImage forKey:beer.imagePath]; 

       // Check to see if the cell for the specified index path is still being used 
       BeerCell *theCell = (BeerCell *)[weakSelf.tableView cellForRowAtIndexPath:indexPath]; 
       // Per the docs. An object representing a cell of the table 
       // or nil if the cell is not visible or indexPath is out of range. 
       if (theCell){ 
        // dispatch onto the main queue because we are doing work on the UI 
        dispatch_async(dispatch_get_main_queue(),^{ 
         theCell.beerImage.image = theImage; 
         [theCell setNeedsLayout]; 
        }); 
       } 
      } 
     }); 
    }   
    else 
    { 
     // Image already exists, use it. 
     cell.beerImage.image = theImage; 
    } 
} 

回答

1

無論何時從磁盤,服務器或渲染圖像加載tableview,您都希望將其放置在後臺隊列中。這樣做是微不足道的,即使在3GS上也會有很好的表現。

我使用類似的方法從非常大的圖像生成tableviews和滾動視圖的縮略圖,性能非常好。

試試這個:

- (void)configureCell:(CustomCell *)cell 
      atIndexPath:(NSIndexPath *)indexPath 
{ 
    CoreDateObject *object = (CoreDateObject *)[self.fetchedResultsController objectAtIndexPath:indexPath]; 
    cell.displayName.text = object.name; 

    // check to see if there is a cached image already. Use a dictionary. 
    // make sure this is one of your ivars 
    UIImage *theImage=[self.imagesCache objectForKey: object.imagePath]; 

    // If the image is not in your cache, you need to retrieve it. 
    if (!theImage){ 
     // The image doesn't exist, we need to load it from disk, web or render it 

     // First put a placeholder image in place. Shouldn't be any penalties after the 
     // first load because it is cached. 
     cell.selectedImage.image=[UIImage imageNamed:@"yourPlaceHolderImage"]; 

     // check to see if your image cache dictionary has been created, if not do so now 
     if (_imagesCache==nil){ 
      _imagesCache=[NSMutableDictionary alloc] initWithCapacity:1]; 
     } 

     // get a weak reference to UITableViewController subclass for use in the block 
     // we do this to avoid retain cycles 
     __weak YourTableViewControllerSubclass *weakSelf=self; 

     // do the heavy lifting on a background queue so the UI looks fast 
     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0); 
     dispatch_async(queue, ^{ 

       theImage=[UIImage imageWithContentOfFile:object.imagePath]; 

       // Add the image to the cache 
       [weakSelf.imagesCache addObject:theImage forKey:object.imagePath]; 

       // Check to see if the cell for the specified index path is still being used 
       CustomCell *theCell=(CustomCell *)[weakSelf.tableView cellForRowAtIndexPath:indexPath]; 
       // Per the docs. An object representing a cell of the table 
       // or nil if the cell is not visible or indexPath is out of range. 
       if (theCell){ 
       // dispatch onto the main queue because we are doing work on the UI 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        theCell.selectedImage.image=theImage 
        [theCell setNeedsLayout]; 
       }); 
       } 

    }else{ 
      // Image already exists, use it. 
      cell.selectedImage.image=theImage; 
    } 

    cell.rating.rate = object.rating.doubleValue; 
} 
+0

我喜歡這個解決方案,但我遇到了一個問題。當我第一次加載表時,應用程序啓動時,我得到的是一個佔位符圖像,直到我滾動表,然後出現正確的圖像,任何想法或建議。我用我使用的代碼編輯了我的答案。 – Vikings 2012-07-14 01:40:33

+0

如果您發現一個幫助解決方案的教程,將非常感謝鏈接 – Vikings 2012-07-14 01:41:55

+0

如果您在應用程序加載時獲取佔位符,並且表格單元格只在您滾動時更新,那麼您做錯了某些事情或者您沒有調整代碼以適應您的具體情況。至於教程,請檢查使用gcd的蘋果wwdc 2011視頻。 – timthetoolman 2012-07-14 06:48:51

0

這兩個環節將更好地解釋這是如何做正確的一個..

https://developer.apple.com/library/ios/#samplecode/LazyTableImages/Introduction/Intro.html(蘋果官方)

https://github.com/rs/SDWebImage(好的庫使用)..

+0

我看了一下延遲加載,但我不是從網絡上獲得的圖像,從盤面 – Vikings 2012-07-05 15:42:22

+1

這是怎麼最初爲什麼它的設計,這只是讀書..但它所做的是將圖像加載過程放在不同的線程上。這將加速加載並使滾動更加流暢。 – DJPlayer 2012-07-05 15:56:44

+0

謝謝我現在給它一個鏡頭 – Vikings 2012-07-05 17:55:16

0

cellForRowAtIndexPath:每當您滾動表格視圖時都會調用...因此,如果您編寫的話,它可能會掛起您的滾動在這種方法中大的處理代碼。因此,如果可能,請使用縮略圖....然後將這些圖像添加到數組中的單元格中。我相信你的滾動會很順利。