iOS多线程自定义operation加载图片 不重复下载图片

摘要:1:ios通过抽象类NSOperation封装了gcd,让ios的多线程变得更为简单易用;

     2:耗时的操作交给子线程来完成,主线程负责ui的处理,提示用户的体验

     2:自定义operation继承自NSOperation,在子线程中下载图片;

   3:保证图片只下载一次,还有保证下载任务不重复

------------------------------------------------------------------------------------

实现原理:1:图片缓存:用字典保存图片和图片的url,key:url  value:图片

     2:任务缓存:用字典保存operation任务和图片的url,key:url  value:operation

先看自定义的operation:.h文件

 1 #import <Foundation/Foundation.h>
 2 @class XBOperation;
 3
 4 @protocol XBOperationDelegate <NSObject>
 5
 6 -(void)operation:(XBOperation *)operation didFinishDownloadImage:(UIImage *)image;
 7
 8 @end
 9 /**
10  *  自定义operation
11  */
12 @interface XBOperation : NSOperation
13
14 // 代理
15 @property (nonatomic, weak)id<XBOperationDelegate> delegate;
16
17 /**
18  *  url
19  */
20 @property (nonatomic, copy) NSString *url;
21 /**
22  *  indexPath 和tableview中的cell相对应
23  */
24 @property (nonatomic, strong) NSIndexPath *indexPath;
25
26 @end

说明:设置代理的目的是等完成下载图片的后通知控制器拿图片

自定义operation的.m文件

@implementation XBOperation

-(void)main
{

    if (self.isCancelled) return;
    NSURL *downloadUrl = [NSURL URLWithString:self.url];
    NSData *data = [NSData dataWithContentsOfURL:downloadUrl]; // 这行会比较耗时

    if (self.isCancelled) return;

    UIImage *image = [UIImage imageWithData:data];

    if (self.isCancelled) return;
    NSLog(@"--%@--", [NSThread currentThread]);

    if ([self.delegate respondsToSelector:@selector(operation:didFinishDownloadImage:)]) {
        dispatch_async(dispatch_get_main_queue(), ^{ // 回到主线程, 传递图片数据给代理对象
            [self.delegate operation:self didFinishDownloadImage:image];
        });
    }
}
@end

说明:重写main方法,在把任务operation加入到队列后,队列会自动调用任务的start方法,start方法内部会调用main方法来完成操作

控制器的tableviewcell数据源的实现

#pragma mark  dataSource数据源方法
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.apps.count;
}

// 数据源方法 实现cell中的内容填充
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *ID = @"app";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
    }

    // 设置数据  XBApp是数据模型
    XBApp *app = self.apps[indexPath.row];

    // 设置标题和子标题
    cell.textLabel.text = app.name;
    cell.detailTextLabel.text = app.download;
    cell.imageView.image = [UIImage imageNamed:@"57437179_42489b0"];

    // 图片数据设置
    UIImage *image = self.imageCache[app.icon];

    if (image) { // 如果图片缓存中有图片 直接加载到
        cell.imageView.image = image;
    }else{ // 如果缓存中没有数据

        // 先设置占位占位图片
        cell.imageView.image = [UIImage imageNamed:@"57437179_42489b0"];

        // 创建自定义的operation 先根据当前要显示图片的url从队列中找到operation 看是否正在下载中
        XBOperation *operationDown = self.operationQueue[app.icon];
        if (!operationDown) { // 如果下载operation不存在 就创建 并添加到队列中
            operationDown = [[XBOperation alloc] init];
            operationDown.delegate = self; // 设置代理
            operationDown.indexPath = indexPath; // 把每个cell与一个operation绑定
            operationDown.url = app.icon;
            // 把operation添加到队列中 会自动调用start方法 然后调用operation的main的方法
            [self.queue addOperation:operationDown];
            // 把operation这个下载任务添加到operation的字典中 防止重复下载
            self.operationQueue[app.icon] = operationDown;
        }

    }

    return cell;

}

// 实现代理方法
-(void)operation:(XBOperation *)operation didFinishDownloadImage:(UIImage *)image
{
    // 必须清楚当前operation 防止由于网络等原因造成的下载失败 而operation还在字典中 这样永远下载不了
    [self.operationQueue removeObjectForKey:operation.url];

    if (image) {
        // 将图片放在缓存字典中
        self.imageCache[operation.url] = image;

        // 刷新表格 单行刷新
        [self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationNone];
    }
}

iOS多线程自定义operation加载图片 不重复下载图片,布布扣,bubuko.com

时间: 06-26

iOS多线程自定义operation加载图片 不重复下载图片的相关文章

iOS面试题之加载单张图片到底会不会崩溃?

今天,一哥们去某公司面试iOS职位.其中一道题目问,加载一张图片,到底会不会崩溃呢? 我拿到这个问题,当时以为是获取网络图片,那还是可能崩溃的,但实际问题,还有半句,图片是本地的... 这问题,加载本地的怎么会崩溃呢?写这么久加载图片也没遇到如此问题. =================================================== 原来,iPhone毕竟是手持设备,它所占有的内存是有限的,当图片过大的时候会引起内存导致的崩溃现象. 后来,我又查了下,发现,原来还有这么大学

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

本文转载至 http://blog.csdn.net/enuola/article/details/8639404 最近做一个项目,需要用到UITableView异步加载图片的例子,看到网上有一个EGOImageView的很好的例子. 但是由于,EGOImageView的实现比较复杂,于是自己就动手做了一个AsynImageView,同样可以实现EGOImageView的效果. 而且自己写的代码比较清晰,容易理解,同样可以实现指定placehoderImage以及指定imageURL,来进行图片

jquery文档加载几种写法,图片加载写法

jquery文档加载写法: $(function(){ }) ; //个人最常使用方式 $(document).ready(function(){ }); //调用文档对象下的ready方法传入一个函数. $(window).load(function() { });//调用window对象下的load方法传入一个函数. (function() { })(jQuery)//()()表示立即执行 并且传入jquery = $ 所以之前$也可以替换为jQuery 注意: jquery的ready只是

Cocos2d-x 3.0多线程异步资源加载

Cocos2d-x从2.x版本到上周刚刚才发布的Cocos2d-x 3.0 Final版,其引擎驱动核心依旧是一个单线程的"死循环",一旦某一帧遇到了"大活儿",比如Size很大的纹理资源加载或网络IO或大量计算,画面将 不可避免出现卡顿以及响应迟缓的现象.从古老的Win32 GUI编程那时起,Guru们就告诉我们:别阻塞主线程(UI线程),让Worker线程去做那些"大活儿"吧. 手机游戏,即便是休闲类的小游戏,往往也涉及大量纹理资源.音视频资

iOS 进度条、加载、安装动画 —— HERO博客

iOS 进度条.加载.安装动画简单实现. 首先看一下效果图: 下面贴上代码: 控制器ViewController: #import <UIKit/UIKit.h> @interface ViewController : UIViewController @end /*** ---------------分割线--------------- ***/ #import "ViewController.h" #import "HWWaveView.h" #im

【JavaScript】加载失败的红叉图片处理与&lt;img&gt;图片标签的onerror事件

大家上网的时候肯定见到过加载失败的红叉图片,具体如下图.当然现在Google Chrome与Firefox对其处理会好看一些. 其实可以利用<img>图片标签的onerror事件对其处理的,要求其加载失败之后,马上加载一张默认图片,而不是显示为红叉叉. 其代码如下: <img src="s.png" onerror="javascript:this.src='xx.png';this.width=80;this.height=80;" />

自定义网络加载中对话框

App在与服务器进行网络交互的时候,需要有一个提示的加载框,如图:,此时我们可以自定义一个加载中的对话框,代码如下: public class LoadingDialog extends Dialog { private static final int CHANGE_TITLE_WHAT = 1; private static final int CHNAGE_TITLE_DELAYMILLIS = 300; private static final int MAX_SUFFIX_NUMBER

Android ListView只加载当前屏幕内的图片(解决list滑动时加载卡顿)

最近在做ListView分页显示,其中包括图片 和文字(先下载解析文字内容,再异步加载图片)发现每次点击下一页后,文字内容加载完毕,马上向下滑动,由于这时后台在用线程池异步下载图片,我每页有20条,也就是20张图片,会导致listview滑动卡顿! 这是用户不想看到的,我参考了网易新闻和电子市场等应用,发现它们都是只加载屏幕内的图片,不现实的不加载,于是我也仿照做了一个.我是菜鸟,我承认 呵呵,虽然不见得完全和他们的一样,但是确实解决了翻页时那一刻的卡顿现象. 因为未发现网上有相关文章,希望对朋

iOS APP中数据加载的6种方式

我们看到的APP,往往有着华丽的启动界面,然后就是漫长的数据加载等待,甚至在无网络的时候,整个处于不可用状态.那么我们怎么处理好界面交互中的加载设计,保证体验无缝衔接,保证用户没有漫长的等待感,而可以轻松自在的享受等待,对加载后的内容有明确的预期呢? 设计师在进行APP设计的设计时,往往会更加专注于界面长什么样,界面和界面之间怎么跳转,给予用户什么样的操作反馈,却偏偏特别容易忽略掉一个比较重要的环节,就是APP数据加载中的设计,所以会导致我们看到的APP,往往有着华丽的启动界面,然后就是漫长的数