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. Vuex基本概念

    Vuex基本概念 State Getter Mutation Action Module 简单的Store import Vue from 'vue'; import Vuex from 'vuex' ...

  2. 初涉KMP算法

    久仰字符串系列理论 KMP 讲解(引用自bzoj3670动物园) 某天,园长给动物们讲解KMP算法. 园长:“对于一个字符串S,它的长度为L.我们可以在O(L)的时间内,求出一个名为next的数组.有 ...

  3. MySQL 查询优化之 Index Condition Pushdown

    MySQL 查询优化之 Index Condition Pushdown Index Condition Pushdown限制条件 Index Condition Pushdown工作原理 ICP的开 ...

  4. 《零基础入门学习Python》【第一版】视频课后答案第006讲

    python中被看作假:FALSE  none 0  ‘ ’  " "  ( ) [ ] { },其他一切都被解释为真 测试题答案: 0.Python 的 floor 除法现在使用 ...

  5. shell-code-5-函数

    # 函数必须在使用前定义 # 如果不写return,将以最后一条命令运行结果,作为返回值. return后跟数值n(0-255) myFistFunc(){ read a read b return ...

  6. 数组dome

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  7. Terracotta服务器的不同配置方式

    Terracotta服务器的不同配置方式 博客分类: 企业应用面临的问题 Java&Socket 开源组件的应用 Terracotta双机多机镜像服务器阵列分片模式企业应用 Terracott ...

  8. hdfs api读写文写件个人练习

    看下hdfs的读写原理,主要是打开FileSystem,获得InputStream or OutputStream: 那么主要用到的FileSystem类是一个实现了文件系统的抽象类,继承来自org. ...

  9. [luoguP1053] 篝火晚会(贪心 + 乱搞)

    传送门 假设第一个位置是1,那么枚举它的左右两边是谁,有两种情况,然后可以递推求出序列. 然后可以贪心,两个序列有多少个不同的数,答案就是多少,具体为啥,yy一下即可 然后就是判断递推求出的序列和目标 ...

  10. [USACO5.3]Big Barn (动态规划)

    题目描述 农夫约翰想要在他的正方形农场上建造一座正方形大牛棚.他讨厌在他的农场中砍树,想找一个能够让他在空旷无树的地方修建牛棚的地方.我们假定,他的农场划分成 N x N 的方格.输入数据中包括有树的 ...