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

原文连接:http://www.cnblogs.com/lesliefang/p/3906708.html


本人在使用过程,觉得对于界面刷新部分需要修改。如果列表下载大量的图片,频繁调用主线程就会出现问题,建议在最后block回调中比对成功后再调用主线程刷新界面。


修改前代码如下:

- (void)downloadImageWithURL:(NSURL *)url complete:(ImageDownloadedBlock)completeBlock{
    LeslieImageCache *imageCache = [LeslieImageCache sharedCache];
    NSString *imageUrl = [url absoluteString];
    UIImage *image = [imageCache getImageFromMemoryForkey:imageUrl];
    // 先从内存中取
    if (image) {
        if (completeBlock) {
            NSLog(@"image exists in memory");
            completeBlock(image,nil,url);
        }
        
        return;
    }
    
    // 再从文件中取
    image = [imageCache getImageFromFileForKey:imageUrl];
    if (image) {
        if (completeBlock) {
            NSLog(@"image exists in file");
            completeBlock(image,nil,url);
        }
        
        // 重新加入到 NSCache 中
        [imageCache cacheImageToMemory:image forKey:imageUrl];
        
        return;
    }
    
    // 内存和文件中都没有再从网络下载
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSError * error;
        NSData *imgData = [NSData dataWithContentsOfURL:url options:NSDataReadingMappedIfSafe error:&error];
        
        dispatch_async(dispatch_get_main_queue(), ^{
            UIImage *image = [UIImage imageWithData:imgData];
            
            if (image) {
                // 先缓存图片到内存
                [imageCache cacheImageToMemory:image forKey:imageUrl];
                
                // 再缓存图片到文件系统
                NSString *extension = [[imageUrl substringFromIndex:imageUrl.length-3] lowercaseString];
                NSString *imageType = @"jpg";
                
                if ([extension isEqualToString:@"jpg"]) {
                    imageType = @"jpg";
                }else{
                    imageType = @"png";
                }
                
                [imageCache cacheImageToFile:image forKey:imageUrl ofType:imageType];
            }
            
            if (completeBlock) {
                completeBlock(image,error,url);
            }
        });
    });
}

- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder{
    // 给  ImageView 设置 tag, 指向当前 url
    self.tag = [url absoluteString];
    
    // 预设一个图片,可以为 nil
    // 主要是为了清除由于复用以前可能存在的图片
    self.image = placeholder;
    
    if (url) {
        // 异步下载图片
        LeslieAsyncImageDownloader *imageLoader = [LeslieAsyncImageDownloader sharedImageLoader];
        [imageLoader downloadImageWithURL:url
                                 complete:^(UIImage *image, NSError *error, NSURL *imageURL) {
                                     // 通过 tag 保证图片被正确的设置
                                     if (image && [self.tag isEqualToString:[imageURL absoluteString]]) {
                                         self.image = image;
                                     }else{
                                         NSLog(@"error when download:%@", error);
                                     }
                                 }];
    }
}


修改后代码如下:

- (void)downloadImageWithURL:(NSURL *)url complete:(ImageDownloadedBlock)completeBlock{
    LeslieImageCache *imageCache = [LeslieImageCache sharedCache];
    NSString *imageUrl = [url absoluteString];
    UIImage *image = [imageCache getImageFromMemoryForkey:imageUrl];
    // 先从内存中取
    if (image) {
        if (completeBlock) {
            NSLog(@"image exists in memory");
            completeBlock(image,nil,url);
        }
        
        return;
    }
    
    // 再从文件中取
    image = [imageCache getImageFromFileForKey:imageUrl];
    if (image) {
        if (completeBlock) {
            NSLog(@"image exists in file");
            completeBlock(image,nil,url);
        }
        
        // 重新加入到 NSCache 中
        [imageCache cacheImageToMemory:image forKey:imageUrl];
        
        return;
    }
    
    // 内存和文件中都没有再从网络下载
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSError * error;
        NSData *imgData = [NSData dataWithContentsOfURL:url options:NSDataReadingMappedIfSafe error:&error];
        
        //dispatch_async(dispatch_get_main_queue(), ^{
            UIImage *image = [UIImage imageWithData:imgData];
            
            if (image) {
                // 先缓存图片到内存
                [imageCache cacheImageToMemory:image forKey:imageUrl];
                
                // 再缓存图片到文件系统
                NSString *extension = [[imageUrl substringFromIndex:imageUrl.length-3] lowercaseString];
                NSString *imageType = @"jpg";
                
                if ([extension isEqualToString:@"jpg"]) {
                    imageType = @"jpg";
                }else{
                    imageType = @"png";
                }
                
                [imageCache cacheImageToFile:image forKey:imageUrl ofType:imageType];
            }
            
            if (completeBlock) {
                completeBlock(image,error,url);
            }
        //});
    });
}


- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder{
    // 给  ImageView 设置 tag, 指向当前 url
    self.tag = [url absoluteString];
    
    // 预设一个图片,可以为 nil
    // 主要是为了清除由于复用以前可能存在的图片
    self.image = placeholder;
    
    if (url) {
        // 异步下载图片
        LeslieAsyncImageDownloader *imageLoader = [LeslieAsyncImageDownloader sharedImageLoader];
        [imageLoader downloadImageWithURL:url
                                 complete:^(UIImage *image, NSError *error, NSURL *imageURL) {
                                     // 通过 tag 保证图片被正确的设置
                                     if (image && [self.tag isEqualToString:[imageURL absoluteString]]) {
					dispatch_async(dispatch_get_main_queue(), ^{
self.image = image;
					});
}else{ NSLog(@"error when download:%@", error); } }]; }}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值