apple sample lazytableimages

1,首先设置横向显示的uitableview

self.customTableview.transform = CGAffineTransformMakeRotation(M_PI/-2);
同时需要将cell也加以旋转否则其内部的图片是反的

cell.contentView.transform = CGAffineTransformMakeRotation(M_PI/2);
2,使用cell的imageview来实现图片的加载

cell.imageView.image = [UIImage imageNamed:@"timeline_image_loading@2x.png"];

这里需要给imageview首先添加占位的图片,否则的话当滚动时后面的cell会因为复用而加载前面已经显示的image
        cell.imageView.frame = CGRectMake(0.0f, 0.0f, cell.frame.size.width, self.customTableview.frame.size.height);
3,判断下载图片

if (!self.record.appIcon)
            {
                {
                    //if the user does not dragging the scroll view then will start the download
                    if (self.customTableview.dragging == NO && self.customTableview.decelerating == NO)
                    {
                        NSString *startURL = self.record.photoURL;
                        //start the download if the image url is no tempty
                        if (startURL && (NSNull*)startURL != [NSNull null])
                        {
                            NSString *endURL = [NSURL URLWithString:startURL];
                            if (endURL)
                            {
                                [self startIconDownload:self.record  withButtonWidth:self.customTableview.frame.size.width andButtonHeight:self.customTableview.frame.size.height forButtonIndex:indexPath.row andIndexPath:indexPath];
                            }
                        }
                    }
                }
                
            }else
            {
                cell.imageView.image = self.record.appIcon;
                [cell.imageView setContentMode:UIViewContentModeScaleAspectFit]; //将裁剪好的图片以指定的大小显示出来
            }
            
- (void)startIconDownload:(PhotosRecord *)appRecord withButtonWidth:(float)width andButtonHeight:(float)height forButtonIndex:(int)tag andIndexPath:(NSIndexPath *)indexPath{
    PhotosDetailDownloader*iconDownloader = [self.imageDownloadsInProgress objectForKey:indexPath];;
    
    if (iconDownloader == nil)
    {
        iconDownloader = [[PhotosDetailDownloader alloc] init];
        iconDownloader.kids = appRecord;
        [iconDownloader setAlbumPhotosDownloadCompletionHandler:^{
            // Display the newly loaded image
            if (appRecord.appIcon){
                NSLog(@"downloaded index here is %d",indexPath.row);
                UITableViewCell *cell = [self.customTableview cellForRowAtIndexPath:indexPath];
                
                cell.imageView.image = appRecord.appIcon;
                [cell.imageView setContentMode:UIViewContentModeScaleAspectFit];
                [cell setNeedsLayout]; //这句很重要,否则下载成功后的首个cell和其后已经在屏幕中显示的cell的image无法显示出来。关于这点详见下面的回复
                [self.imageDownloadsInProgress removeObjectForKey:indexPath];
            }
            
            // Remove the IconDownloader from the in progress list.
            
        }
         ];
        //防止图片重复下载?
        if (iconDownloader) {
            [self.imageDownloadsInProgress setObject:iconDownloader forKey:indexPath];
            
        }
        [iconDownloader startDownloadWithWidth:width andHeight:height];
        [iconDownloader release];
    }
    
}

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?

asked Aug 31 '12 at 5:29
動靜能量
27.7k26178371
 
   
So cell.imageView.image = [UIImage imageWithData:data] works as long as there's been a placeholder image set in the cell within the tableView:cellForRowAtIndexPath:
method, but if you don't provide a placeholder, this same technique
doesn't work? Would you mind posting how you're setting up the
placeholder image?
– 
Carl Veazey
Aug 31 '12 at 5:34
   
@CarlVeazey that's correct. Sure, I set the placeholder using cell.imageView.image = [UIImage imageNamed:@"pic0.png"];
– 
動靜能量
Aug 31 '12 at 5:44

add comment

2 Answers

up vote
5
down vote

accepted

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!

最新文章

  1. poj 3692 Kindergarten (最大独立集)
  2. spicy及remote-viewer登录方法
  3. UI控件tag属性和魔法数字的处理
  4. struts2的action中获得request response session 对象
  5. GetDeviceCaps() 参数
  6. POJ1365 - Prime Land(质因数分解)
  7. Linux系统下如何查看CPU个数
  8. css01
  9. Mysql中Insert into xxx on duplicate key update问题
  10. 天方夜谈·数据结构·List
  11. 删除QQ登录界面的QQ账号信息
  12. cocos2D v3.4 在TileMap中开启高清显示
  13. FreeMaker入门介绍
  14. 黄聪:Mysql主从配置,实现读写分离
  15. [机器学习]集成学习--bagging、boosting、stacking
  16. [jQuery]相对父级元素的fixed定位
  17. app奔溃经验和应对方式
  18. pycharm 下使用tensorflow 之环境配置
  19. kotlin 代码习惯1
  20. 微软职位内部推荐-Senior BSP Engineer

热门文章

  1. 【树形背包】bzoj4033: [HAOI2015]树上染色
  2. 初涉期望dp/概率dp【在更】
  3. Linux rm删除文件未释放空间问题分析
  4. 如何把握好 transition 和 animation 的时序,创作描边按钮特效
  5. 《C/C++工程师综合练习卷》之小试牛刀
  6. H.264 Profile-level-id
  7. 【MySQL】Got fatal error 1236原因和解决方法
  8. mac下secureCRT 客户端 $redis-cli回车后没有反应的解决办法
  9. 【01】git下载和安装的完整过程
  10. TOJ 2710: 过河 路径压缩