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!

关于使用uitableview 中cell 来实现uiimageview的复用和图片的异步加载的更多相关文章

  1. Android中图片的异步加载

    转: 1.  为什么要异步加载图片 下载图片比较费时,先显示文字部分,让加载图片的过程在后台,以提升用户体验 2.  SoftReference的作用 栈内存—引用 堆内存—对象 Eg: Object ...

  2. IOS中UITableView异步加载图片的实现

    本文转载至 http://blog.csdn.net/enuola/article/details/8639404  最近做一个项目,需要用到UITableView异步加载图片的例子,看到网上有一个E ...

  3. Swift - 异步加载各网站的favicon图标,并在单元格中显示

    下面是一个简单的应用,表格视图的各个单元格自动异步加载各个网站的favicon图标,并显示出来. 主要是复习下如何自定义单元格,单元格中图片的异步加载,以及didSet的用法. 效果图如下: 操作步骤 ...

  4. UITableView中cell点击的绚丽动画效果

    UITableView中cell点击的绚丽动画效果 本人视频教程系类   iOS中CALayer的使用 效果图: 源码: YouXianMingCell.h 与 YouXianMingCell.m / ...

  5. UITableView中cell里的UITextField不被弹出键盘挡住

    UITableView中cell里的UITextField不被弹出键盘挡住 本人视频教程系类   iOS中CALayer的使用 效果如下: 源码: EditCell.h 与 EditCell.m // ...

  6. 如何获取UITableView中cell的frame值

    如何获取UITableView中cell的frame值 这个可以用来处理UITableView弹出键盘的问题 本人视频教程系类   iOS中CALayer的使用 效果: 源码: // // ViewC ...

  7. 用适配器模式处理复杂的UITableView中cell的业务逻辑

    用适配器模式处理复杂的UITableView中cell的业务逻辑 适配器是用来隔离数据源对cell布局影响而使用的,cell只接受适配器的数据,而不会与外部数据源进行交互. 源码: ModelCell ...

  8. ios UITableView 异步加载图片并防止错位

    UITableView 重用 UITableViewCell 并异步加载图片时会出现图片错乱的情况 对错位原因不明白的同学请参考我的另外一篇随笔:http://www.cnblogs.com/lesl ...

  9. UIImageView异步加载网络图片

    在iOS开发过程中,经常会遇到使用UIImageView展现来自网络的图片的情况,最简单的做法如下: 去下载https://github.com/rs/SDWebImage放进你的工程里,加入头文件# ...

随机推荐

  1. visibilitychange 标签可见性

    var pageVisibility = document.visibilityState;// 监听 visibility change 事件document.addEventListener('v ...

  2. 使用Redis作为高速缓存

    Redis适合哪些业务场景常规业务系统的数据库访问中,读写操作的比例一般在7/3到9/1,也就是说读操作远多于写操作,因此高并发系统设计里,通过NoSQL技术将热点数据(短期内变动概率小的数据)放入内 ...

  3. [LUOGU] P2196 挖地雷

    题目背景 NOIp1996提高组第三题 题目描述 在一个地图上有N个地窖(N<=20),每个地窖中埋有一定数量的地雷.同时,给出地窖之间的连接路径.当地窖及其连接的数据给出之后,某人可以从任一处 ...

  4. RN原生方法setNativeProps

    https://facebook.github.io/react-native/docs/direct-manipulation.html setNativeProps可以直接修改底层native组件 ...

  5. 【php】 自带的过滤机制

    <?php print_r(filter_list()); ?> 输出类似: Array ( [0] => int [1] => boolean [2] => float ...

  6. Linux Shell脚本教程:30分钟玩转Shell脚本编程

    http://c.biancheng.net/cpp/shell/ Linux在线体验: http://compileonline.com/ Linux命令查询: http://man.linuxde ...

  7. ZOJ 3469 区间DP Food Delivery

    题解 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm ...

  8. 【01】markdown特殊说明

    [01]说明 Markdown 的目标是实现「易读易写」. 可读性,无论如何,都是最重要的.一份使用 Markdown 格式撰写的文件应该可以直接以纯文本发布,并且看起来不会像是由许多标签或是格式指令 ...

  9. enq: TX - row lock contention“等待事件的处理

      enq: TX - row lock contention“等待事件的处理   session1: SQL> conn scott/triger Connected. SQL> CRE ...

  10. Leetcode 335.路径交叉

    路径交叉 给定一个含有 n 个正数的数组 x.从点 (0,0) 开始,先向北移动 x[0] 米,然后向西移动 x[1] 米,向南移动 x[2] 米,向东移动 x[3] 米,持续移动.也就是说,每次移动 ...