NSOperation和NSOperationQueue的理解和学习
来源:互联网 发布:vscode 设置文件类型 编辑:程序博客网 时间:2024/05/21 22:39
NSOperation本身是一个抽象的类,定义了一个要执行的工作。NSOperationQueue是一个工作队列,当NSOperation加入到队列时NSOperationQueue会按照优先级和从属依赖关系组织执行。
从头文件NSOperation.h来看接口是非常的简洁,NSOperation本身是一个抽象类,定义了一个要执行的工作,NSOperationQueue是一个工作队列,当工作加入到队列后,NSOperationQueue会自动按照优先顺序及工作的从属依赖关系(如果有的话)组织执行。
NSOperation是没法直接使用的,它只是提供了一个工作的基本逻辑,具体实现还是需要你通过定义自己的NSOperation子类来获得。如果有必要也可以不将NSOperation加入到一个NSOperationQueue中去执行,直接调用起-start也可以直接执行。
在继承NSOpertaion后,对于非并发的工作,只需要实现NSOperation子类的main方法:
1234567891011
-(void)main { @try { // 处理工作任务 } @catch(...) { // 处理异常,但是不能再重新抛出异常 }}
由于NSOperation的工作是可以取消Cancel的,那么你在main方法处理工作时就需要不断轮询[self isCancelled]确认当前的工作是否被取消了。
如果要支持并发工作,那么NSOperation子类需要至少override这四个方法:
- start
- isConcurrent
- isExecuting
- isFinished
实现了一个基于Operation的下载器,在Sample Code中可以下载。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
- (void)operationDidStart{ [self.lock lock]; NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:self.URL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:self.timeoutInterval]; [request setHTTPMethod: @"GET"]; self.connection =[[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]; [self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; [self.connection start]; [self.lock unlock];}- (void)operationDidFinish{ [self.lock lock]; [self willChangeValueForKey:@"isFinished"]; [self willChangeValueForKey:@"isExecuting"]; self.executing = NO; self.finished = YES; [self didChangeValueForKey:@"isExecuting"]; [self didChangeValueForKey:@"isFinished"]; [self.lock unlock];}- (void)start{ [self.lock lock]; if ([self isCancelled]) { [self willChangeValueForKey:@"isFinished"]; self.finished = YES; [self didChangeValueForKey:@"isFinished"]; return; } [self willChangeValueForKey:@"isExecuting"]; [self performSelector:@selector(operationDidStart) onThread:[[self class] networkThread] withObject:nil waitUntilDone:NO]; self.executing = YES; [self didChangeValueForKey:@"isExecuting"]; [self.lock unlock];}- (void)cancel{ [self.lock lock]; [super cancel]; if (self.connection) { [self.connection cancel]; self.connection = nil; } [self.lock unlock];}- (BOOL)isConcurrent { return YES;}- (BOOL)isExecuting { return self.executing;}- (BOOL)isFinished { return self.finished;}
start方法是工作的入口,通常是你用来设置线程或者其他执行工作任务需要的运行环境的,注意不要调用[super start];isConcurrent是标识这个Operation是否是并发执行的,这里曾经是个坑,如果你没有实现isConcurrent,默认是返回NO,那么你的NSOperation就不是并发执行而是串行执行的,不过在iOS5.0和OS X10.6之后,已经会默认忽略这个返回值,最终和Queue的maxConcurrentOperationCount最大并发操作值相关;isExecuting和isFinished是用来报告当前的工作执行状态情况的,注意必须是线程访问安全的。
注意你的实现要发出合适的KVO通知,因为如果你的NSOperation实现需要用到工作依赖从属特性,而你的实现里没有发出合适的“isFinished”KVO通知,依赖你的NSOperation就无法正常执行。NSOperation支持KVO的属性有:
- isCancelled
- isConcurrent
- isExecuting
- isFinished
- isReady
- dependencies
- queuePriority
- completionBlock
当然也不是说所有的KVO通知都需要自己去实现,例如通常你用不到addObserver到你工作的“isCancelled”属性,你只需要直接调用cancel方法就可以取消这个工作任务。
实现NSOperation子类后,可以直接调用start或者添加到一个NSOperationQueue里:
123
NSOperationQueue *queue = [[NSOperationQueue alloc] init];[queue addOperation:downloader];
NSOperation和NSOperationQueue其他特性
工作是有优先级的,可以通过NSOperation的一下两个接口读取或者设置:
12
- (NSOperationQueuePriority)queuePriority;- (void)setQueuePriority:(NSOperationQueuePriority)p;
工作之间也可有从属依赖关系,只有依赖的工作完成后才会执行:
12
- (void)addDependency:(NSOperation *)op;- (void)removeDependency:(NSOperation *)op;
还可以通过下面接口设置运行NSOpration的子线程优先级:
1
- (void)setQueuePriority:(NSOperationQueuePriority)priority;
如果要设置Queue的并发操作数:
1
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;
iOS4之后还可以往NSOperation上添加一个结束block,用于在工作执行结束之后的操作:
1
- (void)setCompletionBlock:(void (^)(void))block;
如果需要阻塞等待NSOperation工作结束(别在主线程这么干),可以使用接口:
1
- (void)waitUntilFinished;
NSOperationQueue除了添加NSOperation外,也支持直接添加一个Block(iOS4之后):
1
- (void)addOperationWithBlock:(void (^)(void))block
NSOperationQueue可以取消所有添加的工作:
1
- (void)cancelAllOperations;
也可以阻塞式的等待所有工作结束(别在主线程这么干):
1
- (void)waitUntilAllOperationsAreFinished;
在NSOperation对象中获得被添加的NSOperationQueue队列:
1
+ (id)currentQueue
要获得一个绑定在主线程的NSOperationQueue队列:
1
+ (id)mainQueue
NSInvocationOperation & NSBlockOperation
其实除非必要,简单的工作完全可以使用官方提供的NSOperation两个子类NSInvocationOperation和NSBlockOperation来实现。
NSInvocationOperation:
1234
NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(myTaskMethod:) object:data];
NSBlockOperation:
1234
NSBlockOperation* theOp = [NSBlockOperation blockOperationWithBlock: ^{ NSLog(@"Beginning operation.\n"); // Do some work. }];
接口非常简单,一看便会。
- NSOperation和NSOperationQueue的理解和学习
- NSOperationQueue和NSOperation的使用方法
- NSOperationQueue和NSOperation的使用方法
- NSOperationQueue和NSOperation的使用方法
- NSOperation和NSOperationQueue的使用
- NSOperationQueue和NSOperation的使用方法
- NSOperationQueue和NSOperation的使用方法
- NSOperationQueue和NSOperation的使用方法
- Cocoa:NSOperation和NSOperationQueue
- Cocoa:NSOperation和NSOperationQueue
- NSOperation和NSOperationQueue
- Cocoa: NSOperation和NSOperationQueue
- Cocoa:NSOperation和NSOperationQueue
- NSOperation和NSOperationQueue
- NSOperation和NSOperationQueue
- Cocoa:NSOperation和NSOperationQueue
- NSOperation和NSOperationQueue
- NSOperation和NSOperationQueue
- Eclipse 几个常用快捷键
- Jump Game II
- 有关封装和信息隐藏的误区
- 使用pull方式解析XML
- Linux命令----分析内存的瓶颈
- NSOperation和NSOperationQueue的理解和学习
- Java之美[从菜鸟到高手演变]之设计模式二
- ExtJS4中Ajax提交中文参数乱码问题
- 黑马程序员_final关键字的用法
- jquery 子元素过滤器 Child Filters
- 浏览器
- 关于Linux socket通讯中send,recv函数的一个说明
- Mysql事务
- 单例多例详细的解释: