• IOS中级篇—— 多线程--NSOperation


    NSOperation 操作  任务是对代码的封装, 操作是对任务的封装 --目的:就是可以随时的暂停/恢复/取消任务;

    NSOperation
    GCD的封装. OC 运用起来更加方便. 抽象类.

    NSOperation的使用:

    <
    1> 操作直接调用 start方法,就是在当前线程执行(Block中封装的任务数大于1的情况除外).

    <2> 就是将操作放在队列中.自动的帮我们开启线程,来执行操作.

    两个子类:

    NSInvocationOperation:
    调用
         
    1. NSOperation两个子类的使用:
     // 创建一个NSOpertation的子类 NSInvocationOperation
         NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self           selector:@selector(longTimeOperation) object:nil];
         [op1 start];  //调用  开始任务  
          不会开启线程。  在主线程中执行 
     NSBlockOperation:Block
      // 创建一个NSOpertation的子类  NSBlockOperation
        NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
           
    // Block中封装操作.
            [
    self longTimeOperation];
        }];
    // 追加一个操作(任务).
        [op2 addExecutionBlock:^{
            NSLog(@"下载图片1:%@",[NSThread currentThread]);
        }];
      // 追加一个操作(任务).
        [op2 addExecutionBlock:^{
            NSLog(@"下载图片2:%@",[NSThread currentThread]);
        }];
    // [op2 start];
       // NSBlockOperation 直接调用start方法:
       // 如果只有一个任务:在主线程中执行
       // 如果有多个任务:会开启多条线程,在主线程中和子线程中都执行任务.
       // 多个任务都是同时执行的.

        // 操作完成之后的回调(异步的回调)
       
    // 一般用的不多.
        op2.
    completionBlock = ^{
           
    // 操作执行完毕的回调(什么时候操作执行完毕,我们并不知道)
           
    NSLog(@"操作1执行完毕%@",[NSThreadcurrentThread]);
        };
       
     // 创建一个非队列:  非主队列:非主队列存放的操作都在子主线程中执行.
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
     // 获取一个主队列   主队列:主队列存放的操作在主线程中执行
        NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
     // 使用:将操作添加到队列中
        [queue   addOperation:op2];
        [queue addOperation:op1];
     // 将操作添加到队列中,会自动(开启线程)的异步执行操作.
        任务增加到队列中。 就调用Operation里的main方法。  然后自动执行任务     

    任务依赖
        [op1 addDependency:op2];  //等任务 op2 执行完后 在执行op1
        [op2 addDependency:op3];  //等任务 op3 执行完后 在执行op2
         这两句的效果是: op3最先执行 在op2 执行  最后执行 op1
    高级操作:
    一般情况下 队列都用懒加载的方法来实现
    @property (nonatomic, strong) NSOperationQueue *queue;
          // 懒加载Queue
    -(
    NSOperationQueue *)queue
    {
       
    if (!_queue) {
           
    _queue = [[NSOperationQueuealloc] init];
           
    // 最大并发数为6 .
            [
    _queuesetMaxConcurrentOperationCount:6];
        }
       
    return_queue;
    }
    在block中 用到self 都要用weak方式   否则会造循环引用问题
    _weaktypeof(self) wself = self; 
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
          [wself longTimeOperation];
    }];
        // 取消单个操作,一般也不用.
        [op2 cancel];
        // 暂停队列中的操作
        [self.queue setSuspended:YES];
        // 恢复队列中的操作
        [self.queue setSuspended:NO];
        // 取消所有操作,对于已经取消的操作,就永远取消了,不会再次开启
        [self.queue cancelAllOperations];

    // 自定义NSOperation; 线程间通讯
        NSBlockOperation *op = [NSBlockOperationblockOperationWithBlock:^{
           
    // 执行的任务
               
    UIImage *image = [selflongTimeOperation];
               
    NSBlockOperation *op = [NSBlockOperationblockOperationWithBlock:^{
                  self.imageView.image = image;
               }];
            [[NSOperationQueue mainQueue] addOperation:op];
        }];
    下面都是自定义NSOperation方式
    // 不同对象间的通讯
    三种方式
             1.通知
    1.>// 下载图片完成的时候 发送一个通知,将图片传递出去(通知中的参数是image)  
    [[NSNotificationCenter defaultCenter] postNotificationName:@"ITDownloadImageOperation" object:image];

    2.>// 在需要用到内容的类 注册通知的接收者.
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setUpImage:) name:@"ITDownloadImageOperation" object:nil];
    3.>// 通知传递的参数,永远是一个NSNotification;   注册通知时用到的方法
    - (void)setUpImage:(NSNotification *)notify
    {
        // 回到主线程
        dispatch_async(dispatch_get_main_queue(), ^{ 
            NSLog(@"setUpImage%@",[NSThread currentThread]);
            // notify.object就是通知传递的对象.
            // 本次通知中,通知传递的对象就是这个操作
            ITDownloadImageOperation *op = notify.object;
            self.imageView.image = op.image;
        });
    }
           2.代理
                      参考以前代理的写法   一模一样
           3.block
    // 1.定义一个block类型  参数为image
    typedefvoid (^downloadImageOperationBlock)(UIImage *image);
    // 2.定义一个Block的属性
    @property (nonatomic, copy) downloadImageOperationBlock downBlock;
    // 3. 设置Block中想要执行的内容;
    // Block 只是一个块代码.Block中的内容什么时候执行,和定义其中的内容是分开进行的.
    op.downBlock = ^(UIImage *image){
        // Block中想要执行的内容.
        self.imageView.image = image;
    };
    // 4. 在 main执行这个Block  
    -(void)main
    {
        @autoreleasepool {
    // 在子线程下载图片
            UIImage *image = [self downloadImage];
     // 回到主线程
            [[NSOperationQueue mainQueue] addOperationWithBlock:^{
    if (self.downBlock) {
          self.downBlock(image);
          NSLog(@"执行Block中的内容: 设置图片");
    }
    }];
    }
    }
    3.block 方法形式 传单个对象 如UIImage
    前两步 跟上面一样
    // 3.定义一个方法,负责传递Block
    // (downloadImageOperationBlock)blk:Block当做一个参数来传递
    - (void)setUpImageWithBlock:(downloadImageOperationBlock)blk;
    // 4.实现这个方法,self.downBlock赋值
    -(void)setUpImageWithBlock:(downloadImageOperationBlock)blk
    {
        if (blk) {
            // self.downBlock赋值(Block内部执行的方法)
            self.downBlock = blk;
        }
    }
        // 5.Block中的内容是一个参数
        [op setUpImageWithBlock:^(UIImage *image) {
            // 定义一个Block中执行的内容.
            self.imageView.image = image;
        }];
             // 6.调用block  与上面第4步一样
       3.block 方法形式 传本身类    
                        些方法跟 传单个对象用法一模一样 只是在调用bolck时传self
                        self.downBlock(image);
             在设置值的时候 用对象.某个对象
      ITDownloadOperationBlock *op = [[ITDownloadOperationBlockalloc] init];
      [op setUpImageWithBlock:^(ITDownloadOperationBlock *op) {
          self.imageView.image = op.image;
      }];     
       
     
  • 相关阅读:
    删除MFC单文档默认菜单栏的两种方法
    mfc更改背景色
    (转)VC单选按钮控件(Radio Button)用法
    转:MFC 基于对话的程序界面显示完全后立即执行一个函数
    转:vc6以上如何给MFC对话框添加OnInitDialog函数
    常用网址
    2010年春季学期C语言程序设计答疑安排
    rdlc导出Excel
    SQL Server查询表的结构
    C# WinForm开发系列 WebBrowser
  • 原文地址:https://www.cnblogs.com/deng1989/p/4598569.html
Copyright © 2020-2023  润新知