Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
654 views
in Technique[技术] by (71.8m points)

iphone - On iOS, how to make a cell.imageView refresh its content?

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...