0

我在這一整個下午,我無法想象它,所以你的幫助會很棒!我有一個自定義的UICollectionViewCell,裏面填充了我在飛行中創建的圖像。圖像的路徑存儲在分析和查詢完成後,我打電話[self.collectionView reloadData].如何正確加載自定義UICollectionViewCell上的圖像?

在我cellForItemAtIndexPath我有以下代碼:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 

MovieCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath]; 
// Configure the cell 
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"original_title" ascending:YES]; 
[self.moviesforWatchlist sortUsingDescriptors:[NSArray arrayWithObjects:sort, nil]]; 
cell.userInteractionEnabled = YES; 
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; 
[cell addSubview:spinner]; 

NSDictionary *movie = self.moviesforWatchlist[indexPath.row]; 
NSString *moviePosterPath = movie[@"poster_path"]; 
NSString *posterURL = [NSString stringWithFormat:@"http://image.tmdb.org/t/p/w342%@", moviePosterPath]; 
NSURL *posterImage = [NSURL URLWithString:posterURL]; 
UIImage *cachedImage = [self.imageCache objectForKey:posterImage]; 

if (cachedImage) { 
    cell.imageView.image = cachedImage; 
} 
else if (cell.imageView.image == nil) { 
    cell.imageView.image = [UIImage imageNamed:@"default_collectionviewcell.jpeg"]; 
    dispatch_queue_t downloadQueue = dispatch_queue_create("get image data", NULL); 
    dispatch_async(downloadQueue, ^{ 
     [spinner startAnimating]; 
     NSData *imageData = [NSData dataWithContentsOfURL:posterImage]; 
     UIImage *image = [UIImage imageWithData:imageData]; 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [spinner stopAnimating]; 
      MovieCollectionViewCell *updateCell = (id)[collectionView cellForItemAtIndexPath:indexPath]; 
      if (updateCell) { 
       updateCell.imageView.image = image; 
       [updateCell reloadInputViews]; 
       [self.collectionView reloadItemsAtIndexPaths:[self.collectionView indexPathsForVisibleItems]]; 
     } 
     }); 
     [self.imageCache setObject:image forKey:posterImage]; 
    }); 
    } 
[self.collectionView reloadItemsAtIndexPaths:[self.collectionView indexPathsForVisibleItems]]; 
return cell; 
} 

我打電話這樣的查詢方法:

-(void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 
    [self getWatchlistData]; 
    [self.collectionView reloadData]; 
} 

這會導致圖像閃爍,直到圖像加載到UICollectionViewCells。我希望顯示在我的collectionviewcell中的圖像按照字母順序排列,因此我正在排序包含路徑的陣列,在cellforitemsatindexpath這是什麼導致圖像閃爍?或者是別的什麼?非常感謝您的幫助!

回答

-1

嘗試使用DLImageLoader

[[DLImageLoader sharedInstance] displayImageFromUrl:@"image_url_here" 
             imageView:@"UIImageView here"]; 

[[DLImageLoader sharedInstance] loadImageFromUrl:@"image_url_here" 
            completed:^(NSError *error, UIImage *image) { 
             if (error == nil) { 
              // if we have no any errors 
             } else { 
              // if we got an error when load an image 
             } 
            }]; 
0

有許多事情我會改變:

  1. 我不會排序您在cellForItemsAtIndexPAth陣列。當每個單元格都顯示在屏幕上時,會調用該方法,所以如果沒有必要,您可能會多次使用它。如果您的數據在正在創建的單元格與下一個單元格之間發生變化,那麼重新排序可能會混淆collectionView indexPath.row與您的數組索引之間的鏈接。我將在數組填充時對數組進行排序,可能在您的viewWillAppeargetWatchlistData方法中。如果在此之後數據確實發生了變化,請使用其他一些collectionView委託/數據源方法來處理插入/刪除/移動。但我不認爲這是造成圖像閃爍的原因。

  2. 在回發到主隊列的代碼中,您調用cellForItemAtIndexPath方法,更新單元格圖像並調用reloadInputViews(這可能會以某種方式重新配置單元格)。但是,您可以撥打reloadItemsAtIndexPaths查看所有可見的單元格。這樣做會導致您的collectionView重新調用每個可見項目的數據源方法,導致每個圖片都從緩存中重新加載。我認爲這是你閃爍的原因。我只是將下載的圖像保存到緩存中,然後只需調用reloadItemsAtIndexPaths就可以找到一個受影響的indexPath。將調用cellForRowAtIndexPath數據源方法,並將從緩存中恢復圖像並將其添加到新單元中。

  3. 同樣,我認爲cellForItemAtIndexPath末尾的reloadItemsAtIndexPaths是多餘的,可能會導致閃爍。

  4. 我認爲你有一些細胞再利用問題的風險 - 例如,你將微調器添加到每個細胞。但是出隊的單元格可能之前已經顯示過,因此已經有一個微調框(儘管已停止,因此可能已隱藏)。如果你來回滾動很多,你最終可能會得到一些裝有紡紗器的細胞,浪費記憶。在將它添加爲子視圖之前,我會給微調器一個標籤,然後使用viewWithTag來確定是否已將微調器添加到已出隊的單元格中(如果是,請將其刪除)。如有必要,只能添加微調器(即在您的if ...image == nil子句中)。

  5. 也許不太可能,但是如果出列的單元格有一個默認圖像(因此cell.imageView.image!= nil)並且正在被重用於圖像尚未被緩存的單元格(所以cachedImage == nil ),那麼你的調度方法都不會被執行,所以圖像將永遠不會被下載。

對不起,如果這有點重,但我希望它是有用的。

+0

不用擔心!我非常感謝你的反饋。我剛開始學習Objective-C,iOS開發和編程,所以這些答案很棒。我知道我做錯了什麼,但是讓它正常工作仍然取決於我。 關於這個......我認爲它現在正在工作!我在對數組進行排序時,它在getWatchListData方法中填充(這似乎有很大的不同)。基本上,我做了所有的建議。唯一的問題是,在第一次加載時,有時單元格會填充錯誤的圖像。任何想法如何我可以解決這個問題? – bienj0 2014-10-18 10:56:04

+0

只有幾個指針:首先,檢查您的緩存是否正確填充。它可能在之前的運行中被錯誤填充,即使您的代碼現在可能沒問題。其次,注意細胞再利用問題,特別是如果您在滾動列表時看到相同的圖像出現。我發現NSLog和斷點對於追蹤這類問題確實很有幫助。 – pbasdf 2014-10-18 22:48:24

0

我有同樣的問題,當任何圖像下載然後它輕彈視圖。我之前喜歡重新加載那個單元格,所以它會調用一些collectionview的委託方法。所以我刪除它,併爲重新加載單元格單獨的方法。現在當任何新的圖像重新加載,然後我調用這個方法,而不是reloadCellForIndexPath :.在自定義方法中,只需從您的cellForItemAtIndexPath:複製粘貼代碼即可。在自定義方法中分配單元格。 CollectionPhotoItem cell =(CollectionPhotoItem)[self.collection cellForItemAtIndexPath:indexPath];

就是這樣。它會顯示您的手機沒有任何輕拂。謝謝。

相關問題