美文网首页
iOS NSOperation

iOS NSOperation

作者: Rumbles | 来源:发表于2018-07-25 10:43 被阅读12次

    任务配合队列使用 NSOperation、NSOperationQueue?使用的原因

    1.可添加完成的代码块,在操作完成后执行。
    2.添加操作之间的依赖关系,方便的控制执行顺序。
    3.设定操作执行的优先级。
    4.可以很方便的取消一个操作的执行。
    5.使用 KVO 观察对操作执行状态的更改:isExecuteing、isFinished、isCancelled

    6.可以控制线程的数量 通过设置属性maxConcurrentOperationCount [SD 默认是6]

    一.创建普通任务

    1.系统提供 NSInvocationOperation

        NSOperationQueue *queue = [[NSOperationQueue alloc]init];
        NSInvocationOperation *invocation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downLoadImage) object:@""];
        NSInvocationOperation *invocation1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downLoadImage) object:@""];
        NSInvocationOperation *invocation2 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downLoadImage) object:@""];
        [queue addOperation:invocation];//等于调用start方法
        [queue addOperation:invocation1];//等于调用start方法
        [queue addOperation:invocation2];//等于调用start方法
    

    2.系统提供 NSBlockOperation

        //1.创建队列
        NSOperationQueue *queue = [[NSOperationQueue alloc]init];
        
        //2.封装操作
        NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"1----%@",[NSThread currentThread]);
        }];
        
        NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"2----%@",[NSThread currentThread]);
            
        }];
        
        [op2 addExecutionBlock:^{
            NSLog(@"3----%@",[NSThread currentThread]);
        }];
        
        [op2 addExecutionBlock:^{
            NSLog(@"4----%@",[NSThread currentThread]);
        }];
        
        //3.添加操作到队列中
        [queue addOperation:op1];
        [queue addOperation:op2];
    

    3.系统提供 addOperationWithBlock

        NSOperationQueue *queue = [[NSOperationQueue alloc]init];
        [queue addOperationWithBlock:^{
             NSLog(@"1----%@",[NSThread currentThread]);
        }];
        [queue addOperationWithBlock:^{
            NSLog(@"2----%@",[NSThread currentThread]);
        }];
        [queue addOperationWithBlock:^{
            NSLog(@"3----%@",[NSThread currentThread]);
        }];
    

    4.自定义继承与NSOperation的任务

    通过重写 main 或者 start 方法 来定义自己的 NSOperation 对象。重写main方法比较简单,我们不需要管理操作的状态属性 isExecuting 和 isFinished。当 main 执行完返回的时候,这个操作就结束
    #import "WJOperation.h"
    
    @implementation WJOperation
    
    - (void)main
    {
        //耗时操作1
        for (int i = 0; i<1000; i++) {
            NSLog(@"任务1-%d--%@",i,[NSThread currentThread]);
        }
        NSLog(@"+++++++++++++++++++++++++++++++++");
        
        //苹果官方建议,每当执行完一次耗时操作之后,就查看一下当前队列是否为取消状态,如果是,那么就直接退出
        //好处是可以提高程序的性能
        if (self.isCancelled) {
            return;
        }
        
        //耗时操作2
        for (int i = 0; i<1000; i++) {
            NSLog(@"任务2-%d--%@",i,[NSThread currentThread]);
        }
        
        NSLog(@"+++++++++++++++++++++++++++++++++");
    }
    
    @end
    

    二.创建相互依赖任务[图片拼接]

    - (void)download2
    {
        NSLog(@"----");
        //1.创建队列
        NSOperationQueue *queue = [[NSOperationQueue alloc]init];
        
        //2.封装操作下载图片1
        NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
            
            NSURL *url = [NSURL URLWithString:@"http://h.hiphotos.baidu.com/zhidao/pic/item/6a63f6246b600c3320b14bb3184c510fd8f9a185.jpg"];
            NSData *data = [NSData dataWithContentsOfURL:url];
            
            //拿到图片数据
            self.image1 = [UIImage imageWithData:data];
        }];
        
        
        //3.封装操作下载图片2
        NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
            NSURL *url = [NSURL URLWithString:@"http://pic.58pic.com/58pic/13/87/82/27Q58PICYje_1024.jpg"];
            NSData *data = [NSData dataWithContentsOfURL:url];
            
            //拿到图片数据
            self.image2 = [UIImage imageWithData:data];
        }];
        
        //4.合成图片
        NSBlockOperation *combine = [NSBlockOperation blockOperationWithBlock:^{
            
            //4.1 开启图形上下文
            UIGraphicsBeginImageContext(CGSizeMake(200, 200));
            
            //4.2 画image1
            [self.image1 drawInRect:CGRectMake(0, 0, 200, 100)];
            
            //4.3 画image2
            [self.image2 drawInRect:CGRectMake(0, 100, 200, 100)];
            
            //4.4 根据图形上下文拿到图片数据
            UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
            
            //4.5 关闭图形上下文
            UIGraphicsEndImageContext();
            
            //7.回到主线程刷新UI
            [[NSOperationQueue mainQueue]addOperationWithBlock:^{
                self.imageView.image = image;
                NSLog(@"刷新UI---%@",[NSThread currentThread]);
            }];
            
        }];
        
        //5.设置操作依赖
        [combine addDependency:op1];
        [combine addDependency:op2];
        
        //6.添加操作到队列中执行
        [queue addOperation:op1];
        [queue addOperation:op2];
        [queue addOperation:combine];
    }
    

    三.NSOperation 属性

     @property (readonly, getter=isCancelled) BOOL cancelled;//操作是否取消
     @property (readonly, getter=isExecuting) BOOL executing;//是否执行
     @property (readonly, getter=isFinished)  BOOL finished;//是否执行结束
     @property (readonly, getter=isAsynchronous) BOOL asynchronous //是否异步
     @property (readonly, getter=isReady) BOOL ready;//是否处于就绪状态
     @property (readonly, copy) NSArray<NSOperation *> *dependencies;//所有相关依赖
     
     - (void)cancel;//取消操作
     - (void)waitUntilFinished;//执行该操作的时候阻塞当前线程,直到该操作执行
     - (void)addDependency:(NSOperation *)op;//添加依赖
     - (void)removeDependency:(NSOperation *)op;//去除依赖
    

    四. NSOperationQueue的相关属性和方法

    @property (readonly, copy) NSArray<__kindof NSOperation *> *operations;
    @property (readonly) NSUInteger operationCount ;//操作的个数
    @property NSInteger maxConcurrentOperationCount;//最大并发数
    @property (getter=isSuspended) BOOL suspended;//是否悬挂
    @property (nullable, assign  actually retain ) dispatch_queue_t underlyingQueue;//操作队列对应的GCD队列。
    
    - (void)cancelAllOperations;//取消队列中的所有操作。
    
    添加队列
    - (void)addOperation:(NSOperation *)op;
    - (void)addOperations:(NSArray<NSOperation *> *)ops waitUntilFinished:(BOOL)wait ;//可以根据wait参数设置队列中操作的执行方式是串行还是并发。
    - (void)addOperationWithBlock:(void (^)(void))block;
    

    面试问题:
    1.NSOperation有哪些状态:ready executing finished cancelled
    2.NSOperation状态控制?
    (1)如果使用的是NSInvocationOperation NSBlockOperation 状态由系统控制
    (2)如果重写了NSOperation
    1.如果重写了main方法 状态由系统控制
    2.如果重写了start方法 由我们自己控制

    3.系统是如何移除一个isFinish为yes的NSOperation?
    看源码是通过KVO

    相关文章

      网友评论

          本文标题:iOS NSOperation

          本文链接:https://www.haomeiwen.com/subject/rugumftx.html