问题
I am experimenting in tableView:cellForRowAtIndexPath
to set an image by calling
[self downloadImage:urlString andSetIntoCellImageView:cell]
and in downloadImage
, it will call NSURLConnection:sendAsynchronousRequest
(iOS 5 and up only), and in the completion block, set the image by using
cell.imageView.image = [UIImage imageWithData:data]; // data is downloaded data
and it works if in tableView:cellForRowAtIndexPath
, the imageView
is populated with a dummy placeholder image -- and I wonder how the new image is refreshed, is it by setNeedsDisplay
to do a repaint? But if I don't set the placeholder image, then the new image won't show at all. I wonder what mechanism can be used to make it show the image?
If I use
[cell.imageView setNeedsDisplay]
or
[cell setNeedsDisplay];
in the completion block, it won't work, and if I use
[self.table reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
in the completion block by making downloadImage
accept the indexPath
, it will call tableView:cellForRowAtIndexPath
again, and cause an infinite loop. So it seems like I need to use some hash table to remember if the image is already in hash table: if not, call downloadImage
, and if in hash table, simply use it, so there will be no infinite loop.
But is there an easy way to cause the image to show up? Setting a placeholder image works but what if we don't -- by what mechanism does placeholder cause the refresh of image?
回答1:
When a UITableViewCell
's -layoutSubviews
method is called, if its imageView
's image
property is nil
, imageView
is given a frame of (0,0,0,0)
. Also, -layoutSubviews
only is to be called in some situations: when the cell is about to become visible and when it is selected. Not during normal scrolling. So what you've seen is that setting the placeholder inside tableView:cellForRowAtIndexPath:
sizes cell.imageView
to a non-zero size and subsequent changes of the image will be visible.
I fixed the issue by calling [cell setNeedsLayout]
in the completion handler, like so:
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:MY_IMAGE_URL]];
[NSURLConnection sendAsynchronousRequest:request
queue:self.operationQueue
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
UIImage *image = [UIImage imageWithData:data];
cell.imageView.image = image;
[cell setNeedsLayout];
}];
I found the completion block happens in the background so that necessitates performing my UI work on the main thread. Of course this solution won't account for cell reuse and so forth, but at least solves why the cell's image wouldn't appear :)
Hope this helps!
回答2:
This doesn't answer your question directly, but a simple workround to your problem would be to use SDWebImage in your cellForRowAtIndexPath:
instead. The example on their README page does exactly what you are trying to do.
来源:https://stackoverflow.com/questions/12209380/on-ios-how-to-make-a-cell-imageview-refresh-its-content