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

实现效果展示:

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

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

 1 //
 2 //  YYViewController.h
 3 //  01-自定义Operation
 4 //
 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.h
 3 //  01-自定义Operation
 4 //
 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.m
 3 //  01-自定义Operation
 4 //
 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.m
 3 //  01-自定义Operation
 4 //
 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.h
 3 //  01-自定义Operation
 4 //
 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.m
 3 //  01-自定义Operation
 4 //
 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.m
 3 //  01-自定义Operation
 4 //
 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.m
  3 //  01-自定义Operation
  4 //
  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 @end
 20
 21 @implementation YYViewController
 22 #pragma mark- 懒加载apps
 23 -(NSArray *)apps
 24 {
 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-懒加载queue
 41 -(NSOperationQueue *)queue
 42 {
 43     if (_queue==Nil) {
 44         _queue=[[NSOperationQueue alloc]init];
 45         //设置最大并发数为3
 46         _queue.maxConcurrentOperationCount=3;
 47     }
 48     return _queue;
 49 }
 50
 51 #pragma mark-懒加载operations
 52 -(NSMutableDictionary *)operations
 53 {
 54     if (_operations==Nil) {
 55         _operations=[NSMutableDictionary dictionary];
 56     }
 57     return _operations;
 58 }
 59
 60 #pragma mark-懒加载images
 61 -(NSMutableDictionary *)images
 62 {
 63     if (_images==Nil) {
 64         _images=[NSMutableDictionary dictionary];
 65     }
 66     return _images;
 67 }
 68
 69 #pragma mark-数据源方法
 70 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 71 {
 72     return self.apps.count;
 73 }
 74 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 75 {
 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

打印查看:

iOS多线程编程之自定义NSOperation(转载)的更多相关文章

  1. iOS多线程编程之创建线程(转载)

    一.创建和启动线程简单说明 一个NSThread对象就代表一条线程 (1)创建.启动线程 NSThread *thread = [[NSThread alloc] initWithTarget:sel ...

  2. iOS多线程编程原理及实践

    摘要:iOS开发中,开发者不仅要做好iOS的内存管理,而且如果你的iOS涉及多线程,那你也必须了解iOS编程中对多线程的限制,iOS主线程的堆栈大小为1M,其它线程均为512KB,且这个限制开发者是无 ...

  3. iOS多线程编程指南

    iOS多线程编程指南(拓展篇)(1) 一.Cocoa 在Cocoa上面使用多线程的指南包括以下这些: (1)不可改变的对象一般是线程安全的.一旦你创建了它们,你可以把这些对象在线程间安全的传递.另一方 ...

  4. iOS多线程编程Part 2/3 - NSOperation

    多线程编程Part 1介绍了NSThread以及NSRunLoop,这篇Blog介绍另一种并发编程技术:NSOPeration. NSOperation & NSOperationQueue ...

  5. iOS多线程编程--NSOperation(转)

    这篇文章写得非常不错,基础用法都涉及到了,我把文章提到的例子都写到了demo里面, 原文地址: iOS多线程--彻底学会多线程之『NSOperation』 demo下载:https://github. ...

  6. iOS多线程编程技术之NSThread、Cocoa NSOperation、GCD

    原文出处: 容芳志的博客 简介iOS有三种多线程编程的技术,分别是:(一)NSThread(二)Cocoa NSOperation(三)GCD(全称:Grand Central Dispatch) 这 ...

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

    iOS开发多线程篇—自定义NSOperation 一.实现一个简单的tableView显示效果 实现效果展示: 代码示例(使用以前在主控制器中进行业务处理的方式) 1.新建一个项目,让控制器继承自UI ...

  8. IOS高级编程之三:IOS 多线程编程

    多线程的概念在各个操作系统上都会接触到,windows.Linux.mac os等等这些常用的操作系统,都支持多线程的概念. 当然ios中也不例外,但是线程的运行节点可能是我们平常不太注意的. 例如: ...

  9. iOS多线程编程

    废话不多说,直接上干货.先熟悉一下基本知识,然后讲一下常用的两种,NSOperation和GCD. 一.基础概念 进程: 狭义定义:进程是正在运行的程序的实例(an instance of a com ...

随机推荐

  1. Nginx 72万连接性能测试(一)

    转自:http://my.oschina.net/chenzhuo/blog/150200?p=2#comments 根据系统内存64G估算单台tengine做反向代理最高支持72万连接.为了验证达到 ...

  2. [转]window下使用SetUnhandledExceptionFilter捕获让程序的崩溃

    简单使用SetUnhandledExceptionFilter()函数让程序优雅崩溃 虽然是大公司的产品,QQ它还是会在我们的折腾下崩溃的,但是它总是崩溃的很优雅,还要弹出自己的对话框来结束.并且发送 ...

  3. Andoid数据存储之SQLite数据库

    SQLite是一个嵌入式的并且是一个轻量级的数据库: SQLite数据库支持大部分SQL语法, 允许使用SQL语句操作数据库, 其本质是一个文件, 不需要安装启动: SQLite数据库打开只是打开了一 ...

  4. struts1的配置文件详解11111

    要想使用Struts,至少要依靠两个配置文件:web.xml和struts-config.xml.其中web.xml用来安装Struts框架.而struts-config.xml用来配置在Struts ...

  5. artdialog5 bug

    1.使用artdialog5时,使用两个输入框传值,一直无法取到值,使用简单的ID无法取到值,如id=branch..改为id=branch_str_dialog就可以了,问题是解决了,可是没有找到原 ...

  6. Elasticsearch学习之快速入门案例

    1. document数据格式 面向文档的搜索分析引擎 (1)应用系统的数据结构都是面向对象的,复杂的(2)对象数据存储到数据库中,只能拆解开来,变为扁平的多张表,每次查询的时候还得还原回对象格式,相 ...

  7. jquery validate 多种使用方式

    前言:jQuery.validator是一款非常不错的表单验证插件,验证方式非常简单方便,它还对HTML5做了兼容处理,了解了验证规则,就基本掌握了它的使用,下面就让我一一道来 jQuery.vali ...

  8. 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验十三:串口模块② — 接收

    实验十三:串口模块② - 接收 我们在实验十二实现了串口发送,然而这章实验则要实现串口接收 ... 在此,笔者也会使用其它思路实现串口接收. 图13.1 模块之间的数据传输. 假设我们不考虑波特率,而 ...

  9. 使用jvisuamvm的btrace插件

    在之前的文章中写了如何使用btrace来监控运行中的jvm的方法的参数和返回值 jvisualvm中提供了一个btrace插件,我们可以更方便地attach到一个运行中的jvm 更方便地执行和停止bt ...

  10. 应用Strong Name保存.NET应用程序集

    关于Strong Name的主题,网上已经有很多这方面的介绍,你可能最熟悉的印象就是这样 大部分的情况,这样就可以了.如果代码是机密的,还可能用到Delay sign only,这就复杂一些,请查找相 ...