iOS开发多线程篇—自定义NSOperation

一、实现一个简单的tableView显示效果

实现效果展示:

代码示例(使用以前在主控制器中进行业务处理的方式)

1.新建一个项目,让控制器继承自UITableViewController。

 1 //2 //  YYViewController.h3 //  01-自定义Operation4 //5 //  Created by apple on 14-6-26.6 //  Copyright (c) 2014年 itcase. All rights reserved.7 //8 9 #import <UIKit/UIKit.h>
10
11 @interface YYViewController : UITableViewController
12
13 @end

2.处理storyboard中得界面,如下:

3.根据plist文件,字典转模型

新建一个类,继承自NSObject,作为数据的模型

YYappModel.h文件

 1 //2 //  YYappModel.h3 //  01-自定义Operation4 //5 //  Created by apple on 14-6-26.6 //  Copyright (c) 2014年 itcase. All rights reserved.7 //8 9 #import <Foundation/Foundation.h>
10
11 @interface YYappModel : NSObject
12 /**
13  *应用名称
14  */
15 @property(nonatomic,copy)NSString *name;
16 /**
17  *  应用图片
18  */
19 @property(nonatomic,copy)NSString *icon;
20 /**
21  *  应用的下载量
22  */
23 @property(nonatomic,copy)NSString *download;
24
25 +(instancetype)appModelWithDict:(NSDictionary *)dict;
26 -(instancetype)initWithDict:(NSDictionary *)dict;
27 @end

YYappModel.m文件

 1 //2 //  YYappModel.m3 //  01-自定义Operation4 //5 //  Created by apple on 14-6-26.6 //  Copyright (c) 2014年 itcase. All rights reserved.7 //8 9 #import "YYappModel.h"
10
11 @implementation YYappModel
12
13 -(instancetype)initWithDict:(NSDictionary *)dict
14 {
15     if (self=[super init]) {
16         [self setValuesForKeysWithDictionary:dict];
17     }
18     return self;
19 }
20
21 //工厂方法
22 +(instancetype)appModelWithDict:(NSDictionary *)dict
23 {
24     return [[self alloc]initWithDict:dict];
25 }
26 @end

主控制器中得逻辑控制部分,YYViewController.m文件

 1 //2 //  YYViewController.m3 //  01-自定义Operation4 //5 //  Created by apple on 14-6-26.6 //  Copyright (c) 2014年 itcase. All rights reserved.7 //8 9 #import "YYViewController.h"
10 #import "YYappModel.h"
11
12 @interface YYViewController ()
13 @property(nonatomic,strong)NSArray *apps;
14
15 @end
16
17 @implementation YYViewController
18 #pragma mark- 懒加载
19 -(NSArray *)apps
20 {
21     if (_apps==nil) {
22         NSString *path=[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil];
23         NSArray *tempArray=[NSArray arrayWithContentsOfFile:path];
24
25         //字典转模型
26         NSMutableArray *array=[NSMutableArray array];
27         for (NSDictionary *dict in tempArray) {
28             YYappModel *app=[YYappModel appModelWithDict:dict];
29             [array addObject:app];
30         }
31         _apps=array;
32     }
33     return _apps;
34 }
35
36 #pragma mark-数据源方法
37 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
38 {
39     return self.apps.count;
40 }
41
42 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
43 {
44     static NSString *ID=@"ID";
45     UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];
46     if (cell==nil) {
47         cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
48     }
49     YYappModel *app=self.apps[indexPath.row];
50     cell.textLabel.text=app.name;
51     cell.detailTextLabel.text=app.download;
52
53     //下载图片数据
54     NSLog(@"加载图片数据---%@", [NSThread currentThread]);
55     NSURL *url=[NSURL URLWithString:app.icon];
56     NSData *data=[NSData dataWithContentsOfURL:url];
57     UIImage *imgae=[UIImage imageWithData:data];
58     cell.imageView.image=imgae;
59     NSLog(@"完成显示");
60     return cell;
61 }
62
63 @end

打印查看:

二、自定义NSOperation

说明:上面的下载图片数据部分是一个非常耗时的操作,这个操作任务在主线程完成,会严重的影响到用户体验,造成UI卡的现象。下面通过自定义NSOperation,新开线程,让加载图片的任务异步执行。

1.通过代理

在上面的基础上,新建一个类,让其继承自NSOperation。

YYdownLoadOperation.h文件

 1 //2 //  YYdownLoadOperation.h3 //  01-自定义Operation4 //5 //  Created by apple on 14-6-26.6 //  Copyright (c) 2014年 itcase. All rights reserved.7 //8 9 #import <Foundation/Foundation.h>
10
11 #pragma mark-设置代理和代理方法
12 @class YYdownLoadOperation;
13 @protocol YYdownLoadOperationDelegate <NSObject>
14 -(void)downLoadOperation:(YYdownLoadOperation*)operation didFishedDownLoad:(UIImage *)image;
15 @end
16
17 @interface YYdownLoadOperation : NSOperation
18 @property(nonatomic,copy)NSString *url;
19 @property(nonatomic,strong)NSIndexPath *indexPath;
20 @property(nonatomic,strong)id <YYdownLoadOperationDelegate> delegate;
21 @end

YYdownLoadOperation.m文件

 1 //2 //  YYdownLoadOperation.m3 //  01-自定义Operation4 //5 //  Created by apple on 14-6-26.6 //  Copyright (c) 2014年 itcase. All rights reserved.7 //8 9 #import "YYdownLoadOperation.h"
10
11 @implementation YYdownLoadOperation
12 -(void)main
13 {
14     NSURL *url=[NSURL URLWithString:self.url];
15     NSData *data=[NSData dataWithContentsOfURL:url];
16     UIImage *imgae=[UIImage imageWithData:data];
17
18     NSLog(@"--%@--",[NSThread currentThread]);
19     //图片下载完毕后,通知代理
20     if ([self.delegate respondsToSelector:@selector(downLoadOperation:didFishedDownLoad:)]) {
21         dispatch_async(dispatch_get_main_queue(), ^{//回到主线程,传递数据给代理对象
22              [self.delegate downLoadOperation:self didFishedDownLoad:imgae];
23         });
24     }
25 }
26 @end

主控制器中的业务逻辑:

 1 //2 //  YYViewController.m3 //  01-自定义Operation4 //5 //  Created by apple on 14-6-26.6 //  Copyright (c) 2014年 itcase. All rights reserved.7 //8 9 #import "YYViewController.h"
10 #import "YYappModel.h"
11 #import "YYdownLoadOperation.h"
12
13 @interface YYViewController ()<YYdownLoadOperationDelegate>
14 @property(nonatomic,strong)NSArray *apps;
15 @property(nonatomic,strong)NSOperationQueue *queue;
16
17 @end
18
19 @implementation YYViewController
20 #pragma mark- 懒加载apps
21 -(NSArray *)apps
22 {
23     if (_apps==nil) {
24         NSString *path=[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil];
25         NSArray *tempArray=[NSArray arrayWithContentsOfFile:path];
26
27         //字典转模型
28         NSMutableArray *array=[NSMutableArray array];
29         for (NSDictionary *dict in tempArray) {
30             YYappModel *app=[YYappModel appModelWithDict:dict];
31             [array addObject:app];
32         }
33         _apps=array;
34     }
35     return _apps;
36 }
37
38 #pragma mark-懒加载queue
39 -(NSOperationQueue *)queue
40 {
41     if (_queue==Nil) {
42         _queue=[[NSOperationQueue alloc]init];
43         //设置最大并发数为3
44         _queue.maxConcurrentOperationCount=3;
45     }
46     return _queue;
47 }
48
49 #pragma mark-数据源方法
50 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
51 {
52     return self.apps.count;
53 }
54 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
55 {
56     static NSString *ID=@"ID";
57     UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];
58     if (cell==nil) {
59         cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
60     }
61     YYappModel *app=self.apps[indexPath.row];
62     cell.textLabel.text=app.name;
63     cell.detailTextLabel.text=app.download;
64
65     //下载图片数据
66 //    NSLog(@"加载图片数据---%@", [NSThread currentThread]);
67 //    NSURL *url=[NSURL URLWithString:app.icon];
68 //    NSData *data=[NSData dataWithContentsOfURL:url];
69 //    UIImage *imgae=[UIImage imageWithData:data];
70 //    cell.imageView.image=imgae;
71
72     //创建一个OPeration对象
73     YYdownLoadOperation *operation=[[YYdownLoadOperation alloc]init];
74     operation.url=app.icon;
75     operation.indexPath=indexPath;
76     operation.delegate=self;
77
78     //把操作对象添加到队列中在去
79     [self.queue addOperation:operation];
80
81 //    NSLog(@"完成显示");
82     return cell;
83 }
84 -(void)downLoadOperation:(YYdownLoadOperation *)operation didFishedDownLoad:(UIImage *)image
85 {
86     //返回图片数据给每行对应的cell的imageview.image
87     //取出tableview中indexPath这一行对应的cell
88     UITableViewCell *cell=[self.tableView cellForRowAtIndexPath:operation.indexPath];
89     //显示图片
90     cell.imageView.image=image;
91 //    NSLog(@"cell--index--%@---%@",operation.indexPath,[NSThread currentThread]);
92     //一定要刷新表格
93     [self.tableView reloadData];
94     NSLog(@"--%@--",[NSThread currentThread]);
95
96 }
97 @end

说明:通过打印可以发现上面的代码存在很大的问题。

问题1:需要保证一个url对应一个operation对象。

问题2:下载完需要移除。移除执行完毕的操作。

问题3:保证一个url对应一个image。
下面对主控制器中得代码进行改进:
  1 //2 //  YYViewController.m3 //  01-自定义Operation4 //5 //  Created by apple on 14-6-26.6 //  Copyright (c) 2014年 itcase. All rights reserved.7 //8 9 #import "YYViewController.h"10 #import "YYappModel.h"11 #import "YYdownLoadOperation.h"12 13 @interface YYViewController ()<YYdownLoadOperationDelegate>14 @property(nonatomic,strong)NSArray *apps;15 @property(nonatomic,strong)NSOperationQueue *queue;16 @property(nonatomic,strong)NSMutableDictionary *operations;17 @property(nonatomic,strong)NSMutableDictionary *images;18 19 @end20 21 @implementation YYViewController22 #pragma mark- 懒加载apps23 -(NSArray *)apps24 {25     if (_apps==nil) {26         NSString *path=[[NSBundle mainBundle]pathForResource:@"apps.plist" ofType:nil];27         NSArray *tempArray=[NSArray arrayWithContentsOfFile:path];28         29         //字典转模型30         NSMutableArray *array=[NSMutableArray array];31         for (NSDictionary *dict in tempArray) {32             YYappModel *app=[YYappModel appModelWithDict:dict];33             [array addObject:app];34         }35         _apps=array;36     }37     return _apps;38 }39 40 #pragma mark-懒加载queue41 -(NSOperationQueue *)queue42 {43     if (_queue==Nil) {44         _queue=[[NSOperationQueue alloc]init];45         //设置最大并发数为346         _queue.maxConcurrentOperationCount=3;47     }48     return _queue;49 }50 51 #pragma mark-懒加载operations52 -(NSMutableDictionary *)operations53 {54     if (_operations==Nil) {55         _operations=[NSMutableDictionary dictionary];56     }57     return _operations;58 }59 60 #pragma mark-懒加载images61 -(NSMutableDictionary *)images62 {63     if (_images==Nil) {64         _images=[NSMutableDictionary dictionary];65     }66     return _images;67 }68 69 #pragma mark-数据源方法70 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section71 {72     return self.apps.count;73 }74 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath75 {76     static NSString *ID=@"ID";77     UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];78     if (cell==nil) {79         cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];80     }81     YYappModel *app=self.apps[indexPath.row];82     cell.textLabel.text=app.name;83     cell.detailTextLabel.text=app.download;84     85     //保证一个url对应一个image对象86     UIImage *image=self.images[app.icon];87     if (image) {//缓存中有图片88         cell.imageView.image=image;89     }else       //  缓存中没有图片,得下载90     {91         //先设置一张占位图片92         cell.imageView.image=[UIImage imageNamed:@"57437179_42489b0"];93         YYdownLoadOperation *operation=self.operations[app.icon];94         if (operation) {//正在下载95             //什么都不做96         }else  //当前没有下载,那就创建操作97         {98             operation=[[YYdownLoadOperation alloc]init];99             operation.url=app.icon;
100             operation.indexPath=indexPath;
101             operation.delegate=self;
102             [self.queue addOperation:operation];//异步下载
103             self.operations[app.icon]=operation;
104         }
105     }
106
107
108     return cell;
109 }
110 -(void)downLoadOperation:(YYdownLoadOperation *)operation didFishedDownLoad:(UIImage *)image
111 {
112     //1.移除执行完毕的操作
113     [self.operations removeObjectForKey:operation.url];
114
115     //2.将图片放到缓存中
116     self.images[operation.url]=image;
117
118     //3.刷新表格(只刷新下载的那一行)
119
120     [self.tableView reloadRowsAtIndexPaths:@[operation.indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
121     NSLog(@"--%d--%@--",operation.indexPath.row,[NSThread currentThread]);
122
123 }
124 @end

打印查看:

转载于:https://www.cnblogs.com/187n/p/5056714.html

iOS开发多线程篇—自定义NSOperation相关推荐

  1. iOS开发多线程篇—多线程简介

    iOS开发多线程篇-多线程简介 一.进程和线程 1.什么是进程 进程是指在系统中正在执行的一个应用程序 每一个进程之间是独立的.每一个进程均执行在其专用且受保护的内存空间内 比方同一时候打开QQ.Xc ...

  2. iOS开发多线程篇—线程的状态

    iOS开发多线程篇-线程的状态 一.简单介绍 线程的创建: self.thread=[[NSThread alloc]initWithTarget:self selector:@selector(te ...

  3. iOS开发多线程篇—线程安全

    一.多线程的安全隐患 资源共享 1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源 比如多个线程访问同一个对象.同一个变量.同一个文件 当多个线程访问同一块资源时,很容易引发数据错乱和数 ...

  4. iOS开发多线程篇—多线程简单介绍

    一.进程和线程 1.什么是进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开QQ.Xcode,系统就会分别启动2个进程 通过& ...

  5. iOS开发——多线程篇——GCD

    一.基本概念 1.简介 什么是GCD 全称是Grand Central Dispatch,可译为"牛逼的中枢调度器" 纯C语言,提供了非常多强大的函数 GCD的优势 GCD是苹果公 ...

  6. ios开发多线程篇--异步加载网络图片GCD

    一.异步加载网络图片 1.ATS (1)简介 从iOS9.0开始,如果按照以前的方式写代码,在访问网络的时候 ,会报以下警告信息: App Transport Security has blocked ...

  7. iOS开发网络篇—多线程断点下载

    iOS开发网络篇-多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了同时开启多条线程下载一个较大的文件.因为实现过程较为复杂,所以下面贴出完整的代码. 实现思路:下载开始, ...

  8. iOS开发UI篇—使用xib自定义UItableviewcell实现一个简单的团购应用界面布局

    iOS开发UI篇-使用xib自定义UItableviewcell实现一个简单的团购应用界面布局 iOS开发UI篇-使用xib自定义UItableviewcell实现一个简单的团购应用界面布局 一.项目 ...

  9. iOS开发UI篇—transframe属性(形变)

    iOS开发UI篇-transframe属性(形变) 1. transform属性 在OC中,通过transform属性可以修改对象的平移.缩放比例和旋转角度 常用的创建transform结构体方法分两 ...

最新文章

  1. 从FPN到Mask R-CNN,一文告诉你Facebook的计算机视觉有多强
  2. 美宣布制裁中兴通讯 商务部:坚决反对并将交涉
  3. 关于Background-size的几个参数区别
  4. 全数字实时仿真平台SkyEye与SystemC集成进行时序仿真
  5. codevs 5958 无
  6. 《python深度学习》总结与感想
  7. Hazel引擎学习(二)
  8. 全球气象数据的网站集合数据包含(大气数据、海洋数据等各种数据)
  9. 恶意样本分析流程记录
  10. ProjectZomboid服务器搭建
  11. 大学生体育运动网页设计模板代码 DIV布局校园运动网页作业成品 HTML学校网页制作模板 学生简单体育运动网站设计成品
  12. 网络带宽的检测工具介绍
  13. Java实现多个图片转化成PDF
  14. 四大技术峰会30+顶级讲师公布,CCTC 2017盛装启航
  15. ARM7、ARM9、ARM11区别
  16. pr预设的卷及内核锐化是什么_PR内置特效合集
  17. undefinednbsp;methodnbsp;`titl…
  18. dos2unix install on mac_全新的签名工具,支持win,mac
  19. windows下ipython notebook搭建、安装常见问题及Python模块安装
  20. LTC流程概述与核心要点--华为LTC流程专家许浩明老师分享心得体会

热门文章

  1. Windows环境下node.js的安装和配置
  2. Git--团队开发必备神器
  3. oc 计算 带括号 式子
  4. Python即Python解释器的发展史
  5. 第0周学习资源阅读感悟
  6. 【学习】计算几何初步
  7. 有备无患的Linux操作系统备份方法
  8. 如何通过编程方式添加Native Client服务器别名
  9. 获取NT的admin权限的方法
  10. 用两个矩阵的点积计算神经网络的迭代次数 2-8