2015-09-05 134 views
5

嗨,我的問題是,當我滾動TableView時,圖像將出現在錯誤的單元格中,幾秒鐘後出現正確的圖像。UITableView - 滾動時更改單元格圖像

這裏是我的代碼

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 
static NSString *CellIdentifier = @"Cell"; 
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

// Configure the cell... 
if (cell == nil) { 
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] ; 
} 

[cell setOpaque:NO]; 
[cell setBackgroundColor: [UIColor clearColor]]; 

PlaceData *data = [tableData objectAtIndex:indexPath.row]; 
UILabel *nameLabel = (UILabel *)[cell viewWithTag:100]; 
UILabel *sciNameLabel = (UILabel *)[cell viewWithTag:200]; 
UIImageView *thumbnailImageView = (UIImageView *)[cell viewWithTag:300]; 
nameLabel.text = data.name; 
sciNameLabel.text = data.scientific_name; 


// get a dispatch queue 
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
// this will start the image loading in bg 
dispatch_async(concurrentQueue, ^{ 
    NSURL *urlToPicture = [NSURL URLWithString:[NSString stringWithFormat:@"%@", data.thumbnail]]; 
    NSData *imgData = [NSData dataWithContentsOfURL:urlToPicture options:0 error:nil]; 

    // This will set the image when loading is finished 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     UIImage *tmpImage = [[UIImage alloc] initWithData:imgData]; 
     thumbnailImageView.image = tmpImage; 
     //dispatch_release(concurrentQueue); 
     }); 
    }); 

     return cell; 
} 

請幫我

+0

https://stackoverflow.com/questions/43866409/collectionviewview-in-tableviewcell-scroll-isnt-smooth-in-swift3/43907018#43907018 – Sanju

回答

18

你可以嘗試添加以下代碼到你的cellForRowAtIndexPath -

1)指定的索引值,以您的自定義單元格。例如,

cell.tag = indexPath.row 

2)在主線程,圖像分配前,檢查是否圖像通過與標籤匹配它所屬的相應單元格。

dispatch_async(dispatch_get_main_queue(), ^{ 
    if(cell.tag == indexPath.row) { 
     UIImage *tmpImage = [[UIImage alloc] initWithData:imgData]; 
     thumbnailImageView.image = tmpImage; 
    }}); 
}); 
+2

感謝您的回答!這些幫助我解決問題。 –

+1

最佳答案,解決了我的問題 – Jan

4

您重用舊細胞,這是一件好事。但是,您不是在單元格的圖像視圖中初始化圖像,這不是一件好事。你所描述的事情發生的原因是一箇舊的單元格和一個已經爲該單元格加載的圖像被用於新的單元格。然後,您在後臺加載該單元格的圖像(同樣,這很好),但該圖像需要一些時間才能完全加載。同時,顯示已經加載到舊單元格上的圖像(這就是您在該單元格中看到錯誤圖像一段時間的原因)。

解決方案?無論是添加

thumbnailImageView.image = nil 

thumbnailImageView.image = someDefaultImageWhileYourRealOneLoads 

dispatch_queue_t concurrentQueue ...之前。

這樣,當真實的圖像加載時,您將看不到舊的(無關的)圖像。

我希望這會有所幫助。祝你好運。

+0

謝謝你的回答,但它仍然顯示舊圖像 –

+1

謝謝,一直在尋找解決方案几個小時,你的是最容易和最好的一! – DazChong

3

由於您的ImageView正在加載到async調度調用中,該調用不在主線程中,並且正在某個其他線程中調用,所以在從URL中獲取數據並將其轉換爲UIImage 。這個過程需要一點時間,但是你正在以更快的速度滾動tableview。正如你所知,cellForRowAtIndexPath重用了任何窗口外的單元,所以被重用的單元可能不會提取它在窗口中時以前要檢索的圖像數據。因此,它會加載錯誤的數據,然後當針對特定單元格觸發async時,單元格會加載該映像,但會出現延遲。

爲了克服這個功能作爲Chronch指出了這一點u能離開的ImageView作爲零或者你可以使用的AFNetworking具有極好的類加載imageview的圖片相當漂亮

我會離開自己的UA產品類別的UIImageView鏈接到它AFNetworking

+0

感謝您的回覆 –

1

我會做我所有的數據綁定在- tableView:willDisplayCell:forRowAtIndexPath:只是因爲在cellForRowAtIndexPath您的單元尚未繪製。 您可以使用的另一種解決方案是AFNetworking,就像之前提到的其他人一樣。

+1

感謝您的回覆 –

1

斯威夫特3。0

DispatchQueue.main.async(execute: {() -> Void in 

    if cell.tag == indexPath.row { 
     var tmpImage = UIImage(data: imgData) 
     thumbnailImageView.image = tmpImage 
    } 
}) 
0

不要擔心添加兩行,並隨時

cell.thumbnailimages.image=nil 

    cell.thumbnailimages.setImageWith(imageurl!) 

我認爲這兩條線解決您的問題,在此先感謝