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

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

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

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

NSOperation的使用:

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

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

两个子类:

NSInvocationOperation:调用

     1.NSOperation的两个子类的使用:

 //创建一个NSOpertation的子类NSInvocationOperation

    NSInvocationOperation*op1 = [[NSInvocationOperationalloc]initWithTarget:self          selector:@selector(longTimeOperation)object:nil];

     [op1 start];  //调用  开始任务  

      不会开启线程。  在主线程中执行 

 NSBlockOperation:Block

 //创建一个NSOpertation的子类  NSBlockOperation

   NSBlockOperation*op2 = [NSBlockOperationblockOperationWithBlock:^{

       // Block中封装操作.

        [selflongTimeOperation];

    }];

// 追加一个操作(任务).

    [op2addExecutionBlock:^{

       NSLog(@"下载图片1:%@",[NSThreadcurrentThread]);

    }];

  //追加一个操作(任务).

    [op2addExecutionBlock:^{

       NSLog(@"下载图片2:%@",[NSThreadcurrentThread]);

    }];

// [op2 start];

   // NSBlockOperation直接调用start方法:

  //如果只有一个任务:在主线程中执行

  //如果有多个任务:会开启多条线程,在主线程中和子线程中都执行任务.

  //多个任务都是同时执行的.

   //操作完成之后的回调(异步的回调)

   //一般用的不多.

    op2.completionBlock= ^{

       //操作执行完毕的回调(什么时候操作执行完毕,我们并不知道)

       NSLog(@"操作1执行完毕%@",[NSThreadcurrentThread]);

    };

   

 //创建一个非队列:  非主队列:非主队列存放的操作都在子主线程中执行.

   NSOperationQueue*queue = [[NSOperationQueuealloc]init];

 //获取一个主队列   主队列:主队列存放的操作在主线程中执行

   NSOperationQueue*mainQueue = [NSOperationQueuemainQueue];

 //使用:将操作添加到队列中

    [queue   addOperation:op2];

    [queue addOperation:op1];

 //将操作添加到队列中,会自动(开启线程)的异步执行操作.

    任务增加到队列中。 就调用Operation里的main方法。  然后自动执行任务     

任务依赖

   [op1addDependency:op2];  //等任务 op2 执行完后 在执行op1

    [op2addDependency: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 = [NSBlockOperationblockOperationWithBlock:^{

      [wselflongTimeOperation];

}];

    //取消单个操作,一般也不用.

    [op2cancel];

   //暂停队列中的操作

    [self.queuesetSuspended:YES];

   //恢复队列中的操作

    [self.queuesetSuspended:NO];

   //取消所有操作,对于已经取消的操作,就永远取消了,不会再次开启

    [self.queuecancelAllOperations];

//自定义NSOperation;线程间通讯

   NSBlockOperation*op = [NSBlockOperationblockOperationWithBlock:^{

       //执行的任务

           UIImage*image = [selflongTimeOperation];

           NSBlockOperation*op = [NSBlockOperationblockOperationWithBlock:^{

             self.imageView.image= image;

           }];

        [[NSOperationQueuemainQueue]addOperation:op];

    }];

下面都是自定义NSOperation方式

//不同对象间的通讯

三种方式

         1.通知

1.>// 下载图片完成的时候 发送一个通知,将图片传递出去(通知中的参数是image)  

[[NSNotificationCenterdefaultCenter]postNotificationName:@"ITDownloadImageOperation"object:image];

2.>// 在需要用到内容的类注册通知的接收者.

[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(setUpImage:) name:@"ITDownloadImageOperation"object:nil];

3.>//通知传递的参数,永远是一个NSNotification;   注册通知时用到的方法

- (void)setUpImage:(NSNotification*)notify

{

   //回到主线程

   dispatch_async(dispatch_get_main_queue(), ^{ 

       NSLog(@"setUpImage%@",[NSThreadcurrentThread]);

       // 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)downloadImageOperationBlockdownBlock;

// 3. 设置Block中想要执行的内容;

// Block只是一个块代码.Block中的内容什么时候执行,和定义其中的内容是分开进行的.

op.downBlock= ^(UIImage*image){

   // Block中想要执行的内容.

   self.imageView.image= image;

};

// 4. 在main执行这个Block  

-(void)main

{

   @autoreleasepool{

//在子线程下载图片

       UIImage*image = [selfdownloadImage];

 //回到主线程

        [[NSOperationQueuemainQueue]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中的内容是一个参数

    [opsetUpImageWithBlock:^(UIImage*image) {

       //定义一个Block中执行的内容.

       self.imageView.image= image;

    }];

         // 6.调用block  与上面第4步一样

  3.block 方法形式 传本身类    

                    些方法跟 传单个对象用法一模一样 只是在调用bolck时传self

                    self.downBlock(image);

        在设置值的时候 用对象.某个对象

 ITDownloadOperationBlock*op = [[ITDownloadOperationBlockalloc]init];

  [opsetUpImageWithBlock:^(ITDownloadOperationBlock*op) {

     self.imageView.image= op.image;

  }];     

   

 

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航