2016-09-16 52 views
0

我正在開發一個帶有示例UICollectionView的應用程序,該應用程序應該加載它從互聯網上下載的一堆圖標。所以基本上服務器會檢索一個包含JSON文件中每個圖標的URL的列表,然後應用程序解析它,然後每個單元格下載相應的圖像。UICollectionView單元格圖像錯誤

這種方法的問題似乎是,如果用戶在圖像下載時開始滾動,用戶將開始以錯誤的順序看到圖像!這就像UICollectionView試圖「幫助我」一樣,它會呈現出錯的地方!

我見過很多關於這方面的線索,我嘗試了大部分建議,但迄今爲止運氣很好。有人看到這樣的事情?

enter image description here

這是cellForItemAtIndexPath的樣子:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 
PeqImage *image = [self.responseIcons objectAtIndex:indexPath.row]; 

PeqCustomCell *cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:@"PeqCustomCell" forIndexPath:indexPath]; 

cell.peqImage = image; 
cell.imageName = [NSString stringWithFormat:@"%@.png",image.assetId]; 

NSString *theImageUrl = [NSString stringWithFormat:@"http://www.XXXX.com/pb/images/uncompressed/%ld.png",(long)indexPath.row]; 
[cell downloadImage:[NSURL URLWithString:theImageUrl]]; 

return cell; 

}

這是下載算法的樣子(使用的UIImageView + AFNetworking):

- (void) downloadImageWithUrl:(NSURL*) url completion:(PeqCustomCellCompletionBlock)completionBlock 
{UIImage *placeholder = [UIImage imageNamed:@"placeholder"]; 
NSURLRequest *jpegURLRequest = [NSURLRequest requestWithURL:url]; 

self.imageUrl = url.absoluteString;  
[self.imageView setImageWithURLRequest:jpegURLRequest 
        placeholderImage:placeholder 
        success:^(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, UIImage *image) { 
        image = [self normalizeImage:image]; 
        completionBlock(image); 
        } 

        failure:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSError * _Nonnull error) { 

         NSLog(@"Error downloading image from network"); 
        }]; 

}

回答

1

您應該使用SDWebImage library來處理這種東西有點像,

#import <SDWebImage/UIImageView+WebCache.h> 

    .. 

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

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier]; 
if (cell == nil) { 
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
            reuseIdentifier:MyIdentifier] autorelease]; 
} 

// Here we use the new provided sd_setImageWithURL: method to load the web image 
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"] 
        placeholderImage:[UIImage imageNamed:@"placeholder.png"]]; 

cell.textLabel.text = @"My Text"; 
return cell; 
} 

這裏的tableview的例子中,你可以使用相同的爲您collection view

此庫緩存圖像的可重用性。

如果你想實現或知道這個東西native way的話可以參考Loading Images in UICollectionViewCell: Naive to the Clever.

+0

謝謝你的回答。我做了詭計!我正在使用另一個庫 (UIImageView + AFNetworking),但儘管SDWebImage似乎比較慢,但它的工作方式與我期望的那樣可以下載圖像! –

0

問題在於,每當單元格被隱藏並再次顯示時,您都會重新下載圖像。更好的方法是預先下載所有數據,然後使用它填充collectionView。

+0

不,不要提前加載每個圖像。每次按需加載並緩存它們。如果收集視圖有數百個項目,但用戶從不向下滾動以顯示大部分項目,該怎麼辦?爲什麼要在這種情況下下載它們? – rmaddy

1

我懷疑線程是罪魁禍首。所有的UI代碼都必須從主線程調用。現在使用這麼多塊的時候,很容易從後臺線程中意外調用UI調用。當你這樣做時,所有的古怪方式都會開始實現。

我想嘗試改變你的代碼最後一段,以便在主線程上調用圖像調用。我剛剛添加了一個dispatch_async()函數。

self.imageUrl = url.absoluteString; 
[self.imageView setImageWithURLRequest:jpegURLRequest 
         placeholderImage:placeholder 
           success:^(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, UIImage *image){ 
            dispatch_async(dispatch_get_main_queue(), ^{ 
            image = [self normalizeImage:image]; 
            completionBlock(image); 
            }); 
           } 
           failure:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSError * _Nonnull error) { 
            NSLog(@"Error downloading image from network"); 
           }]; 
1

的問題是,集合視圖細胞被重用。因此,您要告訴單元格在屏幕上下載特定圖像,然後在收集視圖需要另一個單元格時重新使用,然後您告訴同一單元格下載另一個圖像。最後下載哪個圖像是最後一個將要顯示的圖像。

在您的下載完成塊中,在設置image = [self normalizeImage:image];之前,您應該檢查請求url是否與當前的self.imageUrl匹配。如果沒有,則該圖像來自舊請求,並且您不希望將其顯示在單元格中。

相關問題