IOS学习之路七(使用 Operation 异步运行任务)
来源:互联网 发布:京东分析与数据库 编辑:程序博客网 时间:2024/06/06 05:54
在 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 *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions{NSNumber *firstNumber = [NSNumber numberWithInteger:111]; NSNumber *secondNumber = [NSNumber numberWithInteger:222];self.firstOperation =[[NSInvocationOperation alloc] initWithTarget:selfselector:@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; @endThe 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, thenwe have to return immediately and generate therequired 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 existsif the taskIsFinished variable is set to YES orthe 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 theloop and we are still complying with the cancellationrules of operations */taskIsFinished = YES;}/* KVO compliance. Generate therequired 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 异步运行任务)
- 使用AsyncTask运行异步任务
- 使用AsyncTask运行异步任务
- Android基础学习之异步任务使用Handler
- Android基础学习之异步任务使用Thread(线程)
- android学习之异步任务AsyncTask
- Android学习之异步任务AsyncTask
- Android学习之异步任务Handler
- Android异步任务之AsyncTask的使用
- Android异步任务之AsyncTask基本使用
- IOS学习之路二十三(EGOImageLoading异步加载图片开源框架使用)
- Linux学习之:七种运行级别
- 浅析AsyncTask运行异步任务
- boost之路 七 异步输入输出
- IOS学习之路七(通过xib自定义UITableViewCell)
- IOS学习之路七(通过xib自定义UITableViewCell)
- IOS学习之路七(通过xib自定义UITableViewCell)
- AsyncTask--异步任务学习
- XCode中如何修改application identifie
- 很好的万年历代码。随时可运行
- Android TextView的跑马灯(不获取焦点情况下也可以跑)
- Maya: 菜单 网格 >平均化顶点
- Linux网络协议栈 -- socket创建(1)
- IOS学习之路七(使用 Operation 异步运行任务)
- Maya: 菜单 网格 >传递属性
- java的几种对象(PO,VO,DAO,BO,POJO)解释
- AekdyCoin出过的ACM题
- Report Server Windows Service (MSSQLSERVER) 无法与报表服务器数据库建立连接
- 开始写博客
- EOS 流程走的最后一步时常出现的错误
- static_cast、dynamic_cast reinterpret_cast和const_cast
- Android中Ringtone播放详解【安卓源码解析五】