NSOperation(基本使用)

NSoperation 和 NSOperationQueue

  • NSOperation 是個(gè)抽象類,并不具備封裝操作的能力,必須使用他的子類
  • 使用NSOperation子類的方式有3種
  • NSInvocationOperation
  • NSBlockOperation
  • 自定義子類繼承NSOperation,實(shí)現(xiàn)內(nèi)部相應(yīng)的方法

基本使用NSOperation

  • NSOperationQueue的隊(duì)列類型
  1. 主隊(duì)列:
  • 初始化方法:[NSOperationQueue mainQueue]
  • 凡是添加到主隊(duì)列中的任務(wù)(NSOperation),都會(huì)放到主隊(duì)列中執(zhí)行
  1. 其他隊(duì)列:
  • 初始化方法:[[NSOperationQueue alloc] init]
  • 同時(shí)包含了:串行、并發(fā)功能
  • 添加這種隊(duì)列的任務(wù)(NSOperation),就會(huì)自動(dòng)放到子線程執(zhí)行

最大并發(fā)操作數(shù)(MaxConcurrentOperationCount)

屬性(suspend)掛起 (Cancel)取消操作

線程的使用

#第一種類型寫法
 // 創(chuàng)建隊(duì)列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    // 創(chuàng)建操作(任務(wù))
    // 創(chuàng)建NSInvocationOperation
    NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download1) object:nil];
    NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download2) object:nil];
    
    // 創(chuàng)建NSBlockOperation
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download3 --- %@", [NSThread currentThread]);
    }];
    
    [op3 addExecutionBlock:^{
        NSLog(@"download4 --- %@", [NSThread currentThread]);
    }];
    [op3 addExecutionBlock:^{
        NSLog(@"download5 --- %@", [NSThread currentThread]);
    }];
    
    
    NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download6 --- %@", [NSThread currentThread]);
    }];
    
    // 創(chuàng)建HBOperation(自定義)
    HBOperation *op5 = [[XMGOperation alloc] init];
    // 添加任務(wù)到隊(duì)列中
    [queue addOperation:op1]; 
// [op1 start] 默認(rèn)已經(jīng)執(zhí)行了
    [queue addOperation:op2]; 
// [op2 start]
    [queue addOperation:op3]; 
// [op3 start]
    [queue addOperation:op4]; 
// [op4 start]
    [queue addOperation:op5];
 // [op5 start]
總結(jié): 先創(chuàng)建隊(duì)列,然后創(chuàng)建操作,在將操作添加到隊(duì)列中執(zhí)行

#第二種類型寫法
// 創(chuàng)建隊(duì)列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [queue addOperationWithBlock:^{
        NSLog(@"download1 --- %@", [NSThread currentThread]);
    }];
    [queue addOperationWithBlock:^{
        NSLog(@"download2 --- %@", [NSThread currentThread]);
    }];
總結(jié): 讓Queue使用block進(jìn)行添加操作(Operation )
# 最大并發(fā)數(shù)
// 創(chuàng)建隊(duì)列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    // 設(shè)置最大并發(fā)操作數(shù)
    //    queue.maxConcurrentOperationCount = 2;
    queue.maxConcurrentOperationCount = 1; // 就變成了串行隊(duì)列
    
    // 添加操作
    [queue addOperationWithBlock:^{
        NSLog(@"download1 --- %@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:0.01];
    }];
    [queue addOperationWithBlock:^{
        NSLog(@"download2 --- %@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:0.01];
    }];
    [queue addOperationWithBlock:^{
        NSLog(@"download3 --- %@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:0.01];
    }];
    [queue addOperationWithBlock:^{
        NSLog(@"download4 --- %@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:0.01];
    }];
    [queue addOperationWithBlock:^{
        NSLog(@"download5 --- %@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:0.01];
    }];
    [queue addOperationWithBlock:^{
        NSLog(@"download6 --- %@", [NSThread currentThread]);
        [NSThread sleepForTimeInterval:0.01];
    }];
總結(jié):最大并發(fā)數(shù)(maxConcurrentOperationCount)默認(rèn)是-1,是否開(kāi)啟多線程取決于最大并發(fā)數(shù)
**************************************************************************
#掛起(suspend)



@interface ViewController ()
/** 隊(duì)列 */
@property (nonatomic, strong) NSOperationQueue *queue;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 創(chuàng)建隊(duì)列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    // 設(shè)置最大并發(fā)操作數(shù)
    queue.maxConcurrentOperationCount = 1; // 就變成了串行隊(duì)列
    
    // 添加操作
    [queue addOperationWithBlock:^{
        for (NSInteger i = 0; i<5000; i++) {
            NSLog(@"download1 -%zd-- %@", i, [NSThread currentThread]);
        }
    }];
    [queue addOperationWithBlock:^{
        for (NSInteger i = 0; i<1000; i++) {
            NSLog(@"download2 --- %@", [NSThread currentThread]);
        }
    }];
    [queue addOperationWithBlock:^{
        for (NSInteger i = 0; i<1000; i++) {
            NSLog(@"download3 --- %@", [NSThread currentThread]);
        }
    }];
    
    
    self.queue = queue;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if (self.queue.isSuspended) {
        // 恢復(fù)隊(duì)列,繼續(xù)執(zhí)行
        self.queue.suspended = NO;
    } else {
        // 暫停(掛起)隊(duì)列,暫停執(zhí)行
        self.queue.suspended = YES;
    }
}
總結(jié):當(dāng)線程掛起的時(shí)候,當(dāng)前線程會(huì)被停止,后面的線程不會(huì)再繼續(xù)執(zhí)行了,如果是當(dāng)前for循環(huán)并沒(méi)有結(jié)束,那么即使是掛起狀態(tài)當(dāng)前for循環(huán)也會(huì)執(zhí)行完成,因?yàn)椋琭or循環(huán)是不可控的。
**************************************************************************
#取消(cancelAllOperations)
[self.queue cancelAllOperations];
總結(jié):取消隊(duì)列中的所有線程
#自定義NSOperation
1. 首先得繼承NSOperation(.h文件)
2.重寫main方法(.m文件)
***********************.m文件**************************
/**
 * 需要執(zhí)行的任務(wù)
 */
- (void)main
{
    for (NSInteger i = 0; i<1000; i++) {
        NSLog(@"download1 -%zd-- %@", i, [NSThread currentThread]);
    }
    if (self.isCancelled) return;
    
    for (NSInteger i = 0; i<1000; i++) {
        NSLog(@"download2 -%zd-- %@", i, [NSThread currentThread]);
    }
    if (self.isCancelled) return;
    
    for (NSInteger i = 0; i<1000; i++) {
        NSLog(@"download3 -%zd-- %@", i, [NSThread currentThread]);
    }
    if (self.isCancelled) return;
}
注意:自定義的Operation需要判斷是否取消了
**********************************************************
# 操作依賴
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download1----%@", [NSThread  currentThread]);
    }];
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download2----%@", [NSThread  currentThread]);
    }];
    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download3----%@", [NSThread  currentThread]);
    }];
    NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
        for (NSInteger i = 0; i<10; i++) {
            NSLog(@"download4----%@", [NSThread  currentThread]);
        }
    }];
    NSBlockOperation *op5 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"download5----%@", [NSThread  currentThread]);
    }];
    op5.completionBlock = ^{
        NSLog(@"op5執(zhí)行完畢---%@", [NSThread currentThread]);
    };
    
    // 設(shè)置依賴
    [op3 addDependency:op1];
    [op3 addDependency:op2];
    [op3 addDependency:op4];
    
    [queue addOperation:op1];
    [queue addOperation:op2];
    [queue addOperation:op3];
    [queue addOperation:op4];
    [queue addOperation:op5];
}
總結(jié):所謂依賴(Dependency)就是當(dāng)前對(duì)象想要執(zhí)行就必須讓他的依賴先完成
所以op3想要先執(zhí)行就必須讓op1 op2 op4 先執(zhí)行,也就是op3 在op1 op2 op4 執(zhí)行后面
**************************************************************************
#實(shí)現(xiàn)進(jìn)程的通信
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    __block UIImage *image1 = nil;
    // 下載圖片1
    NSBlockOperation *download1 = [NSBlockOperation blockOperationWithBlock:^{
        
        // 圖片的網(wǎng)絡(luò)路徑
        NSURL *url = [NSURL URLWithString:@"http://img.pconline.com.cn/images/photoblog/9/9/8/1/9981681/200910/11/1255259355826.jpg"];
        
        // 加載圖片
        NSData *data = [NSData dataWithContentsOfURL:url];
        
        // 生成圖片
        image1 = [UIImage imageWithData:data];
    }];
    
    __block UIImage *image2 = nil;
    // 下載圖片2
    NSBlockOperation *download2 = [NSBlockOperation blockOperationWithBlock:^{
        
        // 圖片的網(wǎng)絡(luò)路徑
        NSURL *url = [NSURL URLWithString:@"http://pic38.nipic.com/20140228/5571398_215900721128_2.jpg"];

        
        // 加載圖片
        NSData *data = [NSData dataWithContentsOfURL:url];
        
        // 生成圖片
        image2 = [UIImage imageWithData:data];
    }];
    
    // 合成圖片
    NSBlockOperation *combine = [NSBlockOperation blockOperationWithBlock:^{
        // 開(kāi)啟新的圖形上下文
        UIGraphicsBeginImageContext(CGSizeMake(100, 100));
        
        // 繪制圖片
        [image1 drawInRect:CGRectMake(0, 0, 50, 100)];
        image1 = nil;
        
        [image2 drawInRect:CGRectMake(50, 0, 50, 100)];
        image2 = nil;
        
        // 取得上下文中的圖片
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        
        // 結(jié)束上下文
        UIGraphicsEndImageContext();
        
        // 回到主線程
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.imageView.image = image;
        }];
    }];
    [combine addDependency:download1];
    [combine addDependency:download2];
    
    [queue addOperation:download1];
    [queue addOperation:download2];
    [queue addOperation:combine];
}
總結(jié):合成圖片必須有兩章圖片,所以得用依賴來(lái)設(shè)置順序,下載圖片,合成圖片都是放在子線程中的刷新UI是返回主線程中的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容