IOS学习之路七(使用 Operation 异步运行任务)
在 application delegate 头文件(.h)中声明一个 operation 队列和两个 invocation operations:
#import <UIKit/UIKit.h>
@interface Running_Tasks_Asynchronously_with_OperationsAppDelegate
: UIResponder <UIApplicationDelegate> @property (nonatomic, strong) UIWindow *window;
@property (nonatomic, strong) NSOperationQueue *operationQueue; @property (nonatomic, strong) NSInvocationOperation *firstOperation; @property (nonatomic, strong) NSInvocationOperation *secondOperation; @end
application delegate 的实现文件(.m 文件)如下:
#import "Running_Tasks_Asynchronously_with_OperationsAppDelegate.h" @implementation Running_Tasks_Asynchronously_with_OperationsAppDelegate @synthesize window = _window;
@synthesize firstOperation;
@synthesize secondOperation;
@synthesize operationQueue;
- (void) firstOperationEntry:(id)paramObject{
NSLog(@"%s", __FUNCTION__);
NSLog(@"Parameter Object = %@", paramObject); NSLog(@"Main Thread = %@", [NSThread mainThread]); NSLog(@"Current Thread = %@", [NSThread currentThread]);
}
- (void) secondOperationEntry:(id)paramObject{
NSLog(@"%s", __FUNCTION__);
NSLog(@"Parameter Object = %@", paramObject); NSLog(@"Main Thread = %@", [NSThread mainThread]); NSLog(@"Current Thread = %@", [NSThread currentThread]);
}
- (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSNumber *firstNumber = [NSNumber numberWithInteger:111]; NSNumber *secondNumber = [NSNumber numberWithInteger:222];
self.firstOperation =[[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(firstOperationEntry:)
object:firstNumber]; self.secondOperation = [[NSInvocationOperation alloc]
initWithTarget:self selector:@selector(secondOperationEntry:) object:secondNumber];
self.operationQueue = [[NSOperationQueue alloc] init]; /* Add the operations to the queue */

[self.operationQueue addOperation:self.firstOperation]; [self.operationQueue addOperation:self.secondOperation];
NSLog(@"Main thread is here");
self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible];
return YES;
} @end
在实现的代码里面都发生了什么呢:
有两个方法:firstOperationEntry:和 secondOperationEntry:,每个方法都接收一个对象
作为参数,并且在控制台窗口打印出当前线程、主线程和参数。这两个入口函数的
invocation operation 将被添加到一个 operation 队列中。
我们初始化两个 NSInvocationOperation 类型对象,并给每个 operation 设置目标
selector 入口点,如之前所述。
然后我们初始化一个 NSOperationQueue 类型对象。(当然也可以在入口方法前面创
建)队列对象将负责管理 operation 对象的并发。
我们调用 NSOperationQueue 的实例方法 addOperation:把每个 invocation operation 添加
到 operation 队列中。在这里,operation 队列可能会也可能不会立即通过 nvocationoperation 的 start 方法启动 invocation operation。但是,需要牢记重要的一点:添加operations 至 operation 队列后,你不能手动启动 operations,必须交由 operation 队列负责。
现在,我们运行一次示例代码,在控制台窗口可以看到如下结果:
[Running_Tasks_Asynchronously_with_OperationsAppDelegate firstOperationEntry:]Main thread is here
Parameter Object = 111
[Running_Tasks_Asynchronously_with_OperationsAppDelegate secondOperationEntry:]Main Thread = <NSThread: 0x6810260>{name = (null), num = 1}
Parameter Object = 222
Current Thread = <NSThread: 0x6805c20>{name = (null), num = 3}Main Thread = <NSThread: 0x6810260>{name = (null), num = 1}Current Thread = <NSThread: 0x6b2d1d0>{name = (null), num = 4}
如果我们子类化了一个 NSOperation 类,并且把这个子类的实例对象添加到了 operation队列,我们需要做稍微的改动。记住以下几点:
由于当把 NSOperation 的子类对象添加到一个 operation 队列中,该对象会异步运行。由此,你必须 overrideNSOperation 的实例方法 isConcurrent,在该方法中返回 YES。 在 start 方法里面执行 main 任务之前,需要定期的调用 isCancelled 方法来检测该函数的返回值,以确定是退出 start 方法还是开始运行 operation。在这里,当 operation 添加到队列中后,operation 的 start 方法将会被 operation 队列调用,start 方法中,调用isCanelled 方法确定 operation 是否被取消。如果 operation 被取消了,只需要从 start
方法中简单的返回即可。如果没被取消,会在 start 方法中调用 main 方法。
在 main task 实现部分中 override main 函数,main 函数将被 operation 执行。在这个函数里面确保分配和初始化 autorelease pool,并且在返回之前释放这个 pool。
重载 operation 的 isFinished 和 isExecuting 方法,这两个函数返回对应的 BOOL 值,代表 operation 是执行完毕还是在执行中。
下面是我们的 operation 声明(.h 文件):
#import <Foundation/Foundation.h>
@interface SimpleOperation : NSOperation
/* Designated Initializer */
- (id) initWithObject:(NSObject *)paramObject; @end
The implementation of the operation is as follows:
#import "SimpleOperation.h" @implementation SimpleOperation NSObject *givenObject;
BOOL finished;
BOOL executing;
- (id) init {
NSNumber *dummyObject = [NSNumber numberWithInteger:123]; return([self initWithObject:dummyObject]);
}
- (id) initWithObject:(NSObject *)paramObject{
self = [super init];
if (self != nil){
/* Keep these values for the main method */
givenObject = paramObject;
}
return(self);
}
- (void) start {
/* If we are cancelled before starting, then
we have to return immediately and generate the
required KVO notifications */
if ([self isCancelled]){
/* If this operation *is* cancelled */
/* KVO compliance */
[self willChangeValueForKey:@"isFinished"];
finished = YES;
[self didChangeValueForKey:@"isFinished"];
return;

} else {
/* If this operation is *not* cancelled */
/* KVO compliance */
[self willChangeValueForKey:@"isExecuting"]; executing = YES;
/* Call the main method from inside the start method */ [self main];
[self didChangeValueForKey:@"isExecuting"];
}
}
- (void) main {
@try {
@autoreleasepool {
/* Keep a local variable here that must get set to YES whenever we are done with the task */
BOOL taskIsFinished = NO;
/* Create a while loop here that only exists
if the taskIsFinished variable is set to YES or
the operation has been cancelled */
while (taskIsFinished == NO &&
[self isCancelled] == NO){
/* Perform the task here */
NSLog(@"%s", __FUNCTION__);
NSLog(@"Parameter Object = %@", givenObject); NSLog(@"Main Thread = %@", [NSThread mainThread]); NSLog(@"Current Thread = %@", [NSThread currentThread]); /* Very important. This way we can get out of the
loop and we are still complying with the cancellation
rules of operations */
taskIsFinished = YES;
}
/* KVO compliance. Generate the
required KVO notifications */
[self willChangeValueForKey:@"isFinished"]; [self willChangeValueForKey:@"isExecuting"]; finished = YES;
executing = NO;
[self didChangeValueForKey:@"isFinished"]; [self didChangeValueForKey:@"isExecuting"]; }
}
@catch (NSException * e) { NSLog(@"Exception %@", e);
}
}
- (BOOL) isConcurrent{
return YES;
}
- (BOOL) isFinished{
/* Simply return the value */
return finished;
}
- (BOOL) isExecuting{
/* Simply return the value */
return executing;
}
@end
现在可以在其他任何类中使用上面定义的这个 operation 类了,比如在 applicationdelegate 中。下面是 application delegate 的声明,使用了新的 operation 类,并将其添加到了新的 operation 队列中:
#import <UIKit/UIKit.h>
@class SimpleOperation;
@interface Running_Tasks_Asynchronously_with_OperationsAppDelegate : UIResponder <UIApplicationDelegate>
@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, strong) NSOperationQueue *operationQueue; @property (nonatomic, strong) SimpleOperation *firstOperation; @property (nonatomic, strong) SimpleOperation *secondOperation;
@end
application delegate 的实现部分如下:
#import "Running_Tasks_Asynchronously_with_OperationsAppDelegate.h" #import "SimpleOperation.h"
@implementation Running_Tasks_Asynchronously_with_OperationsAppDelegate @synthesize window = _window;
@synthesize firstOperation;
@synthesize secondOperation;
@synthesize operationQueue;
- (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ NSNumber *firstNumber = [NSNumber numberWithInteger:111]; NSNumber *secondNumber = [NSNumber numberWithInteger:222]; self.firstOperation = [[SimpleOperation alloc]
initWithObject:firstNumber];
self.secondOperation = [[SimpleOperation alloc] initWithObject:secondNumber];
self.operationQueue = [[NSOperationQueue alloc] init]; /* Add the operations to the queue */ [self.operationQueue addOperation:self.firstOperation]; [self.operationQueue addOperation:self.secondOperation]; NSLog(@"Main thread is here");
self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]]; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible];
return YES;
}
@end
打印到控制台窗口的结果与之前使用并发 invocation operation 类似:
Main thread is here
-[SimpleOperation main]
-[SimpleOperation main]
Parameter Object = 222
Parameter Object = 222
Main Thread = <NSThread: 0x6810260>{name = (null), num = 1}Main Thread = <NSThread: 0x6810260>{name = (null), num = 1}Current Thread = <NSThread: 0x6a10b90>{name = (null), num = 3}Current Thread = <NSThread: 0x6a13f50>{name = (null), num = 4}
IOS学习之路七(使用 Operation 异步运行任务)的更多相关文章
- IOS学习之路七(通过xib自定义UITableViewCell)
一.新建iOS Application工程,选择Single View Application,不要选中Use Storyboard.假设指定的是product name是:UITableViewCe ...
- IOS开发---菜鸟学习之路--(二十二)-近期感想以及我的IOS学习之路
在不知不觉当中已经写了21篇内容 其实一开始是没有想些什么东西的 只是买了Air后 感觉用着挺舒服的,每天可以躺在床上,就一台笔记本,不用网线,不用电源,不用鼠标,不用键盘,干干脆脆的就一台笔记本. ...
- 浅谈iOS学习之路(转)
转眼学习iOS已经快两年的时间了,这个路上有挫折也有喜悦,一步步走过来发现这个过程是我这一辈子的财富,我以前的老大总是对我说,年轻就是最大的资本(本人91年),现在才算是慢慢的体会到,反观自己走过的这 ...
- 浅谈iOS学习之路
转眼学习iOS已经快两年的时间了,这个路上有挫折也有喜悦,一步步走过来发现这个过程是我这一辈子的财富,我以前的老大总是对我说,年轻就是最大的资本(本人91年),现在才算是慢慢的体会到,反观自己走过的这 ...
- IOS学习之路二十三(EGOImageLoading异步加载图片开源框架使用)
EGOImageLoading 是一个用的比较多的异步加载图片的第三方类库,简化开发过程,我们直接传入图片的url,这个类库就会自动帮我们异步加载和缓存工作:当从网上获取图片时,如果网速慢图片短时间内 ...
- IOS学习之路--OC的基础知识
1.项目经验 2.基础问题 3.指南认识 4.解决思路 ios开发三大块: 1.Oc基础 2.CocoaTouch框架 3.Xcode使用 -------------------- CocoaTouc ...
- 纪录我的iOS学习之路
学习资料的网址 田伟宇(Casa Taloyum)有几篇介绍iOS架构的文章,一级棒!原博客链接. iOS应用架构谈 开篇 iOS应用架构谈 view层的组织和调用方案 iOS应用架构谈 网络层设计方 ...
- 我的IOS学习之路(三):手势识别器
在iOS的学习中,对于手势的处理是极为重要的,如对于图片,我们经常需要进行旋转,缩放以及移动等.这里做一下总结,详见代码. - (void)viewDidLoad { [super viewDidLo ...
- 嵌入式Linux驱动学习之路(十三)按键驱动-异步通知
之前的按键方式: 查询: 极度占用CPU资源 中断: 在读的时候产生休眠,在没有信号的时候永远不会返回. poll机制: 在中断的基础上加上超时时间. 异步通知就是通过信号来传送. 首先在应用程序中有 ...
随机推荐
- SQL问题集锦
1.union和union all的区别:http://www.cnblogs.com/xiangshu/articles/2054447.html
- javascript基础08
发现今天居然没有要写,那我就写写之前做的笔记吧. 这是事件的深入: 拖拽逻辑: 第一个: onmousedown : 选择元素 第二个: onmousemove : 移动元素 第三个:onmouseu ...
- 架设证书服务器 及 让IIS启用HTTPS服务(转)
无废话图文教程,教你一步一步搭建CA服务器,以及让IIS启用HTTPS服务. 一.架设证书服务器(CA服务) 1.在系统控制面板中,找到“添加/删除程序”,点击左侧的“添加/删除windows组件”, ...
- jquery判断checkbox是否选中及改变checkbox状态(转)
jquery判断checked的三种方法:.attr('checked): //看版本1.6+返回:”checked”或”undefined” ;1.5-返回:true或false.prop('c ...
- 【CUDA学习】全局存储器
全局存储器,即普通的显存,整个网格中的任意线程都能读写全局存储器的任意位置. 存取延时为400-600 clock cycles 非常容易成为性能瓶颈. 访问显存时,读取和存储必须对齐,宽度为4By ...
- Spring 4.3.2+quartz2.2.3单机、集群+websocket集群实现文本或图片推送、接收及显示
相关环境 Nginx,Spring4.x当前(要选择4.0+),tomcat8.x,Quartz 2.x集群 测试面页:http://sms.reyo.cn/socket.html 测试面页是文本和图 ...
- 田渊栋:AlphaGo系统即使在单机上也有职业水平
Facebook人工智能组研究员田渊栋博士在知乎专栏上更新了一篇文章,详细分析了AlphaGo在<自然>杂志上发表的论文,他认为AlphaGo整个系统即使在单机上也已具有了职业水平,与李世 ...
- WPF 触发器
属性触发器:数据触发器:事件触发器
- LOB字段存放在指定表空间 清理CLOB字段及压缩CLOB空间
LOB字段存放在指定表空间 清理CLOB字段及压缩CLOB空间 把LOB字段的SEGMENT 存放在指定表空间.清理CLOB字段及压缩CLOB空间 1.创建LOB字段存放表空间:create ...
- Navi.Soft30.框架.WebMVC.开发手册
1概述 1.1应用场景 互联网高速发展,互联网软件也随之越来越多,Web程序越来越被广泛使用.它部署简单,维护方便,深得众多软件公司使用 Bootstrap前端框架,是最近非常流行的框架之一.它简洁, ...