• iOS开发系列-NSOperation


    概述

    NSOperation是基于GCD的封装更加面向对象,在使用上也是有任务跟队列的概念,分别对应两个类NSOperation 、NSOperationQueue

    NSOperation和NSOperationQueue实现多线程的具体步骤

    NSOperation

    NSOperation是一个抽象类,使用时候需要使用其子类。NSOperation总共有两个子类。

    • NSInvocationOperation
    • NSBlockOperation

    开发中一般NSOperation子类通常与NSOperationQueue一起使用才能更好的开辟线程。

    NSOperationQueue

    NSOperation可以调用start方法类执行任务,但默认是同步的。如果将NSOperation添加到NSOperationQueue中执行,系统会自动异步执行NSOperation中的操作。

    NSOperationQueue只用两种类型,分别是主队列跟非主队列(包含串行、并发)。两种队列的获取方式:

    [NSOperationQueue mainQueue]; // 主队类
    [[NSOperationQueue alloc] init]; // 非主队列
    

    凡是添加到主队列的任务都是在主线程中执行。非主队列的任务会自动添加到子线程中执行。并发跟串行通过队列的maxConcurrentOperationCount决定。

    #import "ViewController.h"
    @interface ViewController ()
    
    @end
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        
        NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(task) object:nil];
        [queue addOperation:operation];
    //    [operation start];
        
        NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"------------%@", [NSThread currentThread]);
        }];
        // 添加额外的任务才会在子线程执行
        [blockOperation addExecutionBlock:^{
            NSLog(@"------------%@", [NSThread currentThread]);
        }];
        [queue addOperation:blockOperation];
        
    //    [blockOperation start];
        
    }
    
    - (void)task
    {
        NSLog(@"------------%@", [NSThread currentThread]);
    }
    

    一旦NSOperation添加进NSOperationQueue,无须调用NSOperation的start方法,内部自动回调用NSOperation的start。

    开发中还可以自定义NSOperation的方式,重写main方法将任务封装进来。如果任务的代码比较多,在很多程序的很多地方都需要使用,建议采用这种方式。

    #import "FMOperation.h"
    
    @implementation FMOperation
    - (void)main
    {
        // 封装任务
        
    }
    @end
    

    NSOperationQueue的挂起和取消

    设置NSOperationQueue的属性suspended为YES,内部的操作会暂停,在设置suspended为NO时内部的操作会恢复执行。
    注意:当设置NSOperationQueue的suspended为YES时,当前的正在进行的NSOperation中任务会继续执行直到完毕后再暂停。

    调用NSOperationQueue的cancelAllOperations方法相当于调用了内部所有NSOperation内部的cancel方法,一旦取消无法恢复。若想再次执行只能从新添加。
    同样调用cancelAllOperations时执行到一半的NSOperationQueue是没办法中途停止下来直到该NSOperation执行完毕。

    如果我们在自定义的NSOperation的main中封装了大量耗时的操作,苹果建议我们需要在任务中间做判断。提高性能

    #import "FMOperation.h"
    
    @implementation FMOperation
    - (void)main
    {
        // 封装任务
        for (NSInteger i=0; i<10000; i++) {
            NSLog(@"download1-----------");
        }
        
        if (self.isCancelled) return;
        
        for (NSInteger i=0; i<10000; i++) {
            NSLog(@"download2-----------");
        }
        
        if (self.isCancelled) return;
        
        for (NSInteger i=0; i<10000; i++) {
            NSLog(@"download3-----------");
        }
        
        if (self.isCancelled) return;
        
    }
    @end
    

    NSOperation的操作依赖和监听

    默认情况下,添加进队列中操作并发执行时执行顺序是不可控的,这里可以通过设置依赖。并且可以跨队列设置NSOperation依赖。

    #import "ViewController.h"
    @interface ViewController ()
    
    @end
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        
        NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"---------------blockOperation1");
        }];
        
        NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"---------------blockOperation2");
        }];
        
        NSBlockOperation *blockOperation3 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"---------------blockOperation3");
        }];
        
        // 在添加之前设置依赖 让blockOperation3最后执行
        [blockOperation3 addDependency:blockOperation1];
        [blockOperation3 addDependency:blockOperation2];
        
        [queue addOperation:blockOperation1];
        [queue addOperation:blockOperation2];
        [queue addOperation:blockOperation3];
    
    }
    

    通过Operation的completionBlock属性监听某个NSOoperation任务执行完毕。

    #import "ViewController.h"
    @interface ViewController ()
    
    @end
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        
        NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"---------------blockOperation1");
        }];
        
        NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"---------------blockOperation2");
        }];
        
        NSBlockOperation *blockOperation3 = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"---------------blockOperation3");
        }];
        
        // 监听blockOperation2执行完毕
        blockOperation2.completionBlock = ^{
            // blockOperation2执行完毕
        };
        
        [queue addOperation:blockOperation1];
        [queue addOperation:blockOperation2];
        [queue addOperation:blockOperation3];
    
    }
    
  • 相关阅读:
    解决new file()在IOS下不兼容问题
    去除ios上input输入框上方的阴影
    前端不同设备的网页字体设置
    Vue进行请求拦截
    Vue路由拦截
    js判断当前是ios还是android
    身份证号码验证,验证最后一位校验码
    查询MySQL数据表的字段名和表结构
    JAVA中循环删除list中元素的方法总结
    eclipse修改默认注释
  • 原文地址:https://www.cnblogs.com/CoderHong/p/8849641.html
Copyright © 2020-2023  润新知