我正在嘗試加載Flickr照片(cs193p iOS Stanford,作業5)的UITableView列表。爲了避免UI阻塞事件,我推遲了每個單元格的縮略圖下載到不同的隊列中(但是將UI更新回主隊列中)。此代碼不會異步加載圖像,但只要點擊UITableViewCell行就會添加縮略圖。 (見下面的截圖)。任何想法我做錯了什麼?異步UITableViewCell使用GCD加載圖像
PS:我已經看過一些其他的stackoverflow問題& Apple的LazyTableImages示例,但我仍然相信這是達到理想效果的最簡潔的方法。
謝謝!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Photo List Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell
NSDictionary *photo = [self.photoList objectAtIndex:indexPath.row];
if (photo != nil) {
if ([[photo objectForKey:@"title"] length] > 0) {
cell.textLabel.text = [photo objectForKey:@"title"];
} else if ([[[photo objectForKey:@"description"] objectForKey:@"_content"] length] > 0) {
cell.textLabel.text = [[photo objectForKey:@"description"] objectForKey:@"_content"];
} else {
cell.textLabel.text = @"Unknown";
}
}
cell.imageView.image = [[UIImage alloc] initWithCIImage:nil];
// Fetch using GCD
dispatch_queue_t downloadThumbnailQueue = dispatch_queue_create("Get Photo Thumbnail", NULL);
dispatch_async(downloadThumbnailQueue, ^{
UIImage *image = [self getTopPlacePhotoThumbnail:photo];
dispatch_async(dispatch_get_main_queue(), ^{
if ([self.tableView.visibleCells containsObject:cell]) {
[cell.imageView setImage:image];
}
});
});
dispatch_release(downloadThumbnailQueue);
return cell;
}
之前點擊一行
選擇行
更新後:對於那些有興趣,這是我最後使用的代碼:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Photo List Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell
NSDictionary *photo = [self.photoList objectAtIndex:indexPath.row];
if (photo != nil) {
if ([[photo objectForKey:@"title"] length] > 0) {
cell.textLabel.text = [photo objectForKey:@"title"];
} else if ([[[photo objectForKey:@"description"] objectForKey:@"_content"] length] > 0) {
cell.textLabel.text = [[photo objectForKey:@"description"] objectForKey:@"_content"];
} else {
cell.textLabel.text = @"Unknown";
}
}
cell.imageView.image = [[UIImage alloc] initWithCIImage:nil];
// Fetch using GCD
dispatch_queue_t downloadThumbnailQueue = dispatch_queue_create("Get Photo Thumbnail", NULL);
dispatch_async(downloadThumbnailQueue, ^{
UIImage *image = [self getTopPlacePhotoThumbnail:photo];
dispatch_async(dispatch_get_main_queue(), ^{
UITableViewCell *cellToUpdate = [self.tableView cellForRowAtIndexPath:indexPath]; // create a copy of the cell to avoid keeping a strong pointer to "cell" since that one may have been reused by the time the block is ready to update it.
if (cellToUpdate != nil) {
[cellToUpdate.imageView setImage:image];
[cellToUpdate setNeedsLayout];
}
});
});
dispatch_release(downloadThumbnailQueue);
return cell;
}
嘿,這完全是題外話,但不知道是否該塊內發送到主線程,而不是檢查對象上的平等'cell',檢查'indexPath'處的單元格是否存在? –
我剛試過這個:if([self.tableView cellForRowAtIndexPath:indexPath]!= nil){... etc},它的工作原理也很好。這是你想到的嗎? – sybohy
沒錯,不是直接在你的塊中使用'cell.imageView',而是在'indexPath'處抓取單元格並使用它的圖像視圖。我認爲如果直接在主線程塊內使用'cell'的方式,可能會遇到單元複用的問題。 –