·您现在的位置: 江北区云翼计算机软件开发服务部 >> 文章中心 >> 网站建设 >> app软件开发 >> IOS开发 >> IOS中级篇——多线程--NSOperation

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

作者:佚名      IOS开发编辑:admin      更新时间:2022-07-23
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;   }];