NSOperation的简单使用
1.默认情况下,NSOperation并不具备封装操作的能力,必须使用它的子类,使用NSOperation子类的方式有3种:
1> NSInvocationOperation
2> NSBlockOperation
3> 自定义子类继承NSOperation,实现内部相应的方法
这讲先介绍如何用NSOperation封装一个操作,后面再结合NSOperationQueue来使用。
## 一、NSInvocationOperation
NSInvocationOperation *operation = [[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run:) object:@"mj"] autorelease]; 2 [operation start];
* 第1行初始化了一个NSInvocationOperation对象,它是基于一个对象和selector来创建操作
* 第2行调用了start方法,紧接着会马上执行封装好的操作,也就是会调用self的run:方法,并且将@"mj"作为方法参数
* 这里要注意:默认情况下,调用了start方法后并不会开一条新线程去执行操作,而是在当前线程同步执行操作。只有将operation放到一个NSOperationQueue中,才会异步执行操作。
## 二、NSBlockOperation
### 1.同步执行一个操作
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){ 2 NSLog(@"执行了一个新的操作");
3 }];
4 // 开始执行任务
5 [operation start];
* 第1行初始化了一个NSBlockOperation对象,它是用一个Block来封装需要执行的操作
* 第2行调用了start方法,紧接着会马上执行Block中的内容
* 这里还是在当前线程同步执行操作,并没有异步执行
### 2.并发执行多个操作
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){
2 NSLog(@"执行第1次操作,线程:%@", [NSThread currentThread]);
3 }];
4
5 [operation addExecutionBlock:^() {
6 NSLog(@"又执行了1个新的操作,线程:%@", [NSThread currentThread]);
7 }];
8
9 [operation addExecutionBlock:^() {
10 NSLog(@"又执行了1个新的操作,线程:%@", [NSThread currentThread]);
11 }];
12
13 [operation addExecutionBlock:^() {
14 NSLog(@"又执行了1个新的操作,线程:%@", [NSThread currentThread]);
15 }];
16
17 // 开始执行任务
18 [operation start];
* 第1行初始化了一个NSBlockOperation对象
* 分别在第5、9、13行通过addExecutionBlock:方法添加了新的操作,包括第1行的操作,一共封装了4个操作
* 在第18行调用start方法后,就会并发地执行这4个操作,也就是会在不同线程中执行
<pre style="margin: 0px; padding: 0px; overflow: auto; white-space: pre; word-wrap: break-word; font-family: "Courier New" !important; font-size: 18px !important;">1 2013-02-02 21:38:46.102 thread[4602:c07]
又执行了1个新的操作,线程:<NSThread: 0x7121d50>{name = (null), num = 1} 2 2013-02-02 21:38:46.102 thread[4602:3f03]
又执行了1个新的操作,线程:<NSThread: 0x742e1d0>{name = (null), num = 5} 3 2013-02-02 21:38:46.102 thread[4602:1b03]
执行第1次操作,线程:<NSThread: 0x742de50>{name = (null), num = 3}
4 2013-02-02 21:38:46.102 thread[4602:1303] 又执行了1个新的操作,线程:<NSThread: 0x7157bf0>{name = (null), num = 4}</pre>
可以看出,每个操作所在线程的num值都不一样,说明是不同线程
## 三、NSOperation的其他用法
### 1.取消操作
operation开始执行之后, 默认会一直执行操作直到完成,我们也可以调用cancel方法中途取消操作
### 2.在操作完成后做一些事情
如果想在一个NSOperation执行完毕后做一些事情,就调用NSOperation的setCompletionBlock方法来设置想做的事情
operation.completionBlock = ^() {
NSLog(@"执行完毕");
}
当operation封装的操作执行完毕后,就会回调Block里面的内容
## 四、自定义NSOperation
如果NSInvocationOperation和NSBlockOperation不能满足需求,我们可以直接新建子类继承NSOperation,并添加任何需要执行的操作。如果只是简单地自定义NSOperation,只需要重载-(void)main这个方法,在这个方法里面添加需要执行的操作。
下面写个子类DownloadOperation来下载图片
### 1.继承NSOperation,重写main方法
#### DownloadOperation.h
#import <Foundation/Foundation.h>
@protocol DownloadOperationDelegate;
@interface DownloadOperation : NSOperation // 图片的url路径
@property (nonatomic, copy) NSString *imageUrl; // 代理
@property (nonatomic, assign) id<DownloadOperationDelegate> delegate;
- (id)initWithUrl:(NSString *)url delegate:(id<DownloadOperationDelegate>)delegate;
@end
// 图片下载的协议
@protocol DownloadOperationDelegate <NSObject>
- (void)downloadFinishWithImage:(UIImage *)image; @end
#### DownloadOperation.m
#import "DownloadOperation.h"
2
3 @implementation DownloadOperation
4 @synthesize delegate = _delegate; //使用@synthesize 只有一个目的——给实例变量起个别名,或者说为同一个变量添加两个名字。
5 @synthesize imageUrl = _imageUrl;
6
7 // 初始化
8 - (id)initWithUrl:(NSString *)url delegate:(id<DownloadOperationDelegate>)delegate {
9 if (self = [super init]) {
10 self.imageUrl = url;
11 self.delegate = delegate;
12 }
13 return self;
14 }
15 // 释放内存
16 - (void)dealloc {
17 [super dealloc];
18 [_imageUrl release];
19 }
20
21 // 执行主任务
22 - (void)main {
23 // 新建一个自动释放池,如果是异步执行操作,那么将无法访问到主线程的自动释放池
24 @autoreleasepool {
25 // ....
26 }
27 }
28 @end
* 在第22行重载了main方法,等会就把下载图片的代码写到这个方法中
* 如果这个DownloadOperation是在异步线程中执行操作,也就是说main方法在异步线程调用,那么将无法访问主线程的自动释放池,所以在第24行创建了一个属于当前线程的自动释放池
### 2.正确响应取消事件
* 默认情况下,一个NSOperation开始执行之后,会一直执行任务到结束,就比如上面的DownloadOperation,默认会执行完main方法中的所有代码。
* NSOperation提供了一个cancel方法,可以取消当前的操作。
* 如果是自定义NSOperation的话,需要手动处理这个取消事件。比如,一旦调用了cancel方法,应该马上终止main方法的执行,并及时回收一些资源。
* 处理取消事件的具体做法是:在main方法中定期地调用isCancelled方法检测操作是否已经被取消,也就是说是否调用了cancel方法,如果返回YES,表示已取消,则立即让main方法返回。
* 以下地方可能需要调用isCancelled方法:
* 在执行任何实际的工作之前,也就是在main方法的开头。因为取消可能发生在任何时候,甚至在operation执行之前。
* 执行了一段耗时的操作之后也需要检测操作是否已经被取消
1 - (void)main {
2 // 新建一个自动释放池,如果是异步执行操作,那么将无法访问到主线程的自动释放池
3 @autoreleasepool {
4 if (self.isCancelled) return;
5
6 // 获取图片数据
7 NSURL *url = [NSURL URLWithString:self.imageUrl];
8 NSData *imageData = [NSData dataWithContentsOfURL:url];
9
10 if (self.isCancelled) {
11 url = nil;
12 imageData = nil;
13 return;
14 }
15
16 // 初始化图片
17 UIImage *image = [UIImage imageWithData:imageData];
18
19 if (self.isCancelled) {
20 image = nil;
21 return;
22 }
23
24 if ([self.delegate respondsToSelector:@selector(downloadFinishWithImage:)]) {
25 // 把图片数据传回到主线程
26 [(NSObject *)self.delegate performSelectorOnMainThread:@selector(downloadFinishWithImage:) withObject:image waitUntilDone:NO];
27 }
28 }
29 }</pre>
* 在第4行main方法的开头就先判断operation有没有被取消。如果被取消了,那就没有必要往下执行了
* 经过第8行下载图片后,在第10行也需要判断操作有没有被取消
* 总之,执行了一段比较耗时的操作之后,都需要判断操作有没有被取消
* 图片下载完毕后,在第26行将图片数据传递给了代理(delegate)对象
NSOperation的简单使用的更多相关文章
- 3.多线程NSOperation
1.NSOperation的基本操作 使用NSOperation的两个子类,NSInvocationOperation 和 NSBlockOperation 创建操作,然后将操作添加到队列中去执行 / ...
- iOS开发之多线程技术——NSOperation篇
本篇将从四个方面对iOS开发中使用到的NSOperation技术进行讲解: 一.什么是NSOperation 二.我们为什么使用NSOperation 三.在实际开发中如何使用NSOperation ...
- 多线程编程2 - NSOperation
一.NSOperation 1.简介 NSOperation实例封装了需要执行的操作和执行操作所需的数据,并且能够以并发或非并发的方式执行这个操作. NSOperation本身是抽象基类,因此必须使用 ...
- iOS开发多线程--(NSOperation/Queue)
iOS实现多线程的方式有三种,分别是NSThread.NSOperation.GCD. 关于GCD,请阅读GCD深入浅出学习 简介 NSOperation封装了需要执行的操作和执行操作所需的数据,提供 ...
- IOS开发 多线程编程 - NSOperation
一.NSOperation 1.简介 NSOperation实例封装了需要执行的操作和执行操作所需的数据,并且能够以并发或非并发的方式执行这个操作. NSOperation本身是抽象基类,因此必须使用 ...
- 如何使用NSOperations和NSOperationQueues(二)
"每一个应用程序至少有一个主线程.线程的工作就是去执行一系列的指令.在Cocoa Touch中,主线程包含应用程序的主运行回路.几乎所有你写的代码都会在主线程中执行,除非你特别创建" ...
- 如何使用NSOperations和NSOperationQueues 第一部分
这篇文章还可以在这里找到 英语 学习如何在你的app中使用NSOperations! 这篇博客是由iOS个人开发者Soheil Moayedi Azarpour发布的. 每个人都会在使用iOS或者Ma ...
- iOS开发多线程篇—NSOperation简单介绍
iOS开发多线程篇—NSOperation简单介绍 一.NSOperation简介 1.简单说明 NSOperation的作⽤:配合使用NSOperation和NSOperationQueue也能实现 ...
- iOS 多线程 简单学习NSThread NSOperation GCD
1:首先简单介绍什么叫线程 可并发执行的,拥有最小系统资源,共享进程资源的基本调度单位. 共用堆,自有栈(官方资料说明iOS主线程栈大小为1M,其它线程为512K). 并发执行进度不可控,对非原子操作 ...
随机推荐
- 动态搜索图书:可以按书名、作者、出版社以及价格范围进行搜索。(在IDEA中mybatis)
中午找了好久.好多人写的都驴头不对马嘴.自己实现后.才发现是真的不麻烦.也不知道人家咋想的.写的死麻烦还没用.老是搜出sql语句写死的.我要的是动态滴.自己写出后.总结了一下 1.按照书名.作者.出版 ...
- 一天十道Java面试题----第一天(面向对象-------》ArrayList和LinkedList)
这里是参考B站上的大佬做的面试题笔记.大家也可以去看视频讲解!!! 文章目录 1.面向对象 2.JDK.JRE.JVM区别和联系 3.==和equals 4.final 5.String .Strin ...
- 1.Django-Rest-Framework入门规范
一.WEB应用模式 1.前后端不分离 前后端混合开发(前后端不分离),返回的是html的内容,需要渲染页面,写模版 2.前后端分离 专注于后端接口,返回json.xml格式的数据 二.AP ...
- 【一】ERNIE:飞桨开源开发套件,入门学习,看看行业顶尖持续学习语义理解框架,如何取得世界多个实战的SOTA效果?
参考文章: 深度剖析知识增强语义表示模型--ERNIE_财神Childe的博客-CSDN博客_ernie模型 ERNIE_ERNIE开源开发套件_飞桨 https://github.com/Pad ...
- LINQ使用小贴士
LINQ中的排序操作符 OrderBy:按升序对序列的元素进行排序.OrderByDescending:按降序对序列的元素排序.ThenBy:按升序对序列中的元素执行后续排序.ThenByDescen ...
- 题解 UVA439 骑士的移动 Knight Moves
前言 最近板子题刷多了-- 题意 一个 \(8\times 8\) 的棋盘,问马从起点到终点的最短步数为多少. \(\sf Solution\) 要求最短路径嘛,显然 bfs 更优. 读入 这个读入处 ...
- <二>掌握构造函数和析构函数
构造函数 和类名相同,可以带参数,参数可以有多个 构造函数执行完成后,内存开辟完成,同时可以完成初始化工作. 析构函数 ~Test(); 析构函数可以自己调用,析构函数调用后,对象不存在了.自己调了析 ...
- 嵌入式-C语言:通过结构体指针操作结构体内容
#include<stdio.h> #include<string.h> struct Student { char name[32]; int age; int height ...
- Java新特性(2):Java 10以后
您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来- 虽然到目前为止Java的版本更新还没有什么惊天动地的改变,但总是会冒出一些有趣的小玩意.前面列举了Java9和Java10的一些特色,现在接着来 ...
- MVC开发单元测试小工具 —— 搜寻还没写单元测试的方法
方法比较笨,有更好的建议可以提. 写这个工具呢,因为要写单元测试,保证代码质量,方便修改维护.一切为了自己方便.当然这个算是个人开发的项目 1.MVC中控制器建立个基类(这个光明正大的抄袭的),控制往 ...