上篇轉載的博文有講解多線程的幾種使用,但是NSOperation的介紹不夠詳細,在此做一下補充。 NSOperation本身是不能直接用來操作的,需要繼承NSOperation實現相應的方法或者直接使用NSBlockOperation、NSInvocationOperation才能正常使用。下面就分別從自定義、NSBlockOperation、NSInvocationOperation三個方面來講解: 1、自定義
//// PHOperation.h// OperationTest//// Created by 項普華 on 2017/2/9.// 郵箱: xiangpuhua@126.com// 電話: +86 13316987488// 主頁: https://github.com/xphaijj// Copyright ? 2017年 項普華. All rights reserved.//#import <Foundation/Foundation.h>typedef void(^DownloadBlock)(id file);@interface PHOperation : NSOperation/** * 線程執行下載任務 * * @param urlString 需要下載的地址 * @param downloadBlock 下載完成的回調 * * @return 當前類的實例 */- (id)initWithDownloadURL:(NSString *)urlString block:(DownloadBlock)downloadBlock;@end//// PHOperation.m// OperationTest//// Created by 項普華 on 2017/2/9.// 郵箱: xiangpuhua@126.com// 電話: +86 13316987488// 主頁: https://github.com/xphaijj// Copyright ? 2017年 項普華. All rights reserved.//#import "PHOperation.h"@interface PHOperation () {}@PRoperty (nonatomic, strong) NSString *urlStr;@property (nonatomic, copy) DownloadBlock block;@end@implementation PHOperation/** * 線程執行下載任務 * * @param urlString 需要下載的地址 * @param downloadBlock 下載完成的回調 * * @return 當前類的實例 */- (id)initWithDownloadURL:(NSString *)urlString block:(DownloadBlock)downloadBlock { self = [super init]; if (self) { _urlStr = urlString; _block = downloadBlock; } return self;}/** * 自定義main方法執行線程任務 */- (void)main { @try { @autoreleasepool { if (self.isCancelled) { return; } NSURL *url = [NSURL URLWithString:self.urlStr]; NSData *data = [NSData dataWithContentsOfURL:url]; if (self.isCancelled) { url = nil; data = nil; return; } if (self.block) { self.block(data); } } } @catch (NSException *exception) { } @finally { }}@end同步引用方法如下:
NSLog(@"start"); PHOperation *op = [[PHOperation alloc] initWithDownloadURL:@"https://www.lsd1888.com/res/21/57e77030f3d1d.jpg" block:^(id file) { sleep(4); UIImage *image = [UIImage imageWithData:file]; NSLog(@"%@ %@", image, [NSThread currentThread]); }]; [op start];//執行同步操作 NSLog(@"end");輸出結果: 2017-02-09 12:31:41.320 OperationTest[4553:996304] start 2017-02-09 12:31:45.730 OperationTest[4553:996304] , {320, 353} {number = 1, name = main} 2017-02-09 12:31:45.730 OperationTest[4553:996304] end 由輸出結果我們可知,同步引用正常調起。
異步引用方法如下:
NSLog(@"start"); NSOperationQueue *phQueue = [[NSOperationQueue alloc] init]; PHOperation *op = [[PHOperation alloc] initWithDownloadURL:@"https://www.lsd1888.com/res/21/57e77030f3d1d.jpg" block:^(id file) { sleep(4); UIImage *image = [UIImage imageWithData:file]; NSLog(@"%@ %@", image, [NSThread currentThread]); }]; [phQueue addOperation:op];//執行異步操作 NSLog(@"end");輸出結果: 2017-02-09 12:28:57.248 OperationTest[4493:979978] start 2017-02-09 12:28:57.249 OperationTest[4493:979978] end 2017-02-09 12:29:01.601 OperationTest[4493:980384] , {320, 353} {number = 5, name = (null)}
由輸出結果我們可知異步引用正常調起。
NSLog(@"start"); PHOperation *op = [[PHOperation alloc] initWithDownloadURL:@"https://www.lsd1888.com/res/21/57e77030f3d1d.jpg" block:^(id file) { sleep(4); UIImage *image = [UIImage imageWithData:file]; NSLog(@"1 %@ %@", image, [NSThread currentThread]); }]; PHOperation *op1 = [[PHOperation alloc] initWithDownloadURL:@"https://www.lsd1888.com/res/21/57e77030f3d1d.jpg" block:^(id file) { sleep(2); UIImage *image = [UIImage imageWithData:file]; NSLog(@"2 %@ %@", image, [NSThread currentThread]); }]; [op start]; [op1 start]; NSLog(@"end");輸出結果: 2017-02-09 13:09:52.308 OperationTest[5420:1208386] start 2017-02-09 13:09:56.622 OperationTest[5420:1208386] 1 , {320, 353} {number = 1, name = main} 2017-02-09 13:09:58.852 OperationTest[5420:1208386] 2 , {320, 353} {number = 1, name = main} 2017-02-09 13:09:58.853 OperationTest[5420:1208386] end 由輸出結果可知,op與op1執行了同步。
NSLog(@"start"); NSOperationQueue *queue = [[NSOperationQueue alloc] init]; PHOperation *op = [[PHOperation alloc] initWithDownloadURL:@"https://www.lsd1888.com/res/21/57e77030f3d1d.jpg" block:^(id file) { sleep(4); UIImage *image = [UIImage imageWithData:file]; NSLog(@"1 %@ %@", image, [NSThread currentThread]); }]; PHOperation *op1 = [[PHOperation alloc] initWithDownloadURL:@"https://www.lsd1888.com/res/21/57e77030f3d1d.jpg" block:^(id file) { sleep(2); UIImage *image = [UIImage imageWithData:file]; NSLog(@"2 %@ %@", image, [NSThread currentThread]); }]; [queue addOperation:op]; [queue addOperation:op1]; NSLog(@"end");輸出結果: 2017-02-09 13:13:20.089 OperationTest[5510:1234538] start 2017-02-09 13:13:20.090 OperationTest[5510:1234538] end 2017-02-09 13:13:22.440 OperationTest[5510:1234706] 2 , {320, 353} {number = 5, name = (null)} 2017-02-09 13:13:24.534 OperationTest[5510:1234688] 1 , {320, 353} {number = 6, name = (null)} 由輸出結果可知:op與op1之間執行了的是異步。
2、NSBlockOperation
NSLog(@"start"); NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ sleep(4); NSLog(@"op1"); }]; [op1 start];//同步執行 NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"op2"); }]; [op2 start];//同步執行 NSLog(@"end");輸出結果: 2017-02-09 12:46:57.590 OperationTest[4835:1073639] start 2017-02-09 12:47:01.684 OperationTest[4835:1073639] op1 2017-02-09 12:47:01.684 OperationTest[4835:1073639] op2 2017-02-09 12:47:01.685 OperationTest[4835:1073639] end 由輸出結果可知,以上方法均同步執行。
NSLog(@"start"); NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ sleep(4); NSLog(@"op1"); }]; [op1 start];//同步執行 NSBlockOperation *op2 = [[NSBlockOperation alloc] init]; [op2 addExecutionBlock:^{//異步操作 sleep(3); NSLog(@"start"); }]; [op2 addExecutionBlock:^{ sleep(1); NSLog(@"middle"); }]; [op2 addExecutionBlock:^{ sleep(2); NSLog(@"end1"); }]; [op2 setCompletionBlock:^{ NSLog(@"op2 done"); }]; [op2 start];//同步執行 NSLog(@"end");輸出結果: 2017-02-09 12:51:41.925 OperationTest[4975:1102448] start 2017-02-09 12:51:45.997 OperationTest[4975:1102448] op1 2017-02-09 12:51:47.072 OperationTest[4975:1102542] middle 2017-02-09 12:51:48.070 OperationTest[4975:1102539] end1 2017-02-09 12:51:49.073 OperationTest[4975:1102448] start 2017-02-09 12:51:49.073 OperationTest[4975:1102448] end 2017-02-09 12:51:49.073 OperationTest[4975:1102539] op2 done 由上述執行結果可知:op1與op2之間同步執行,op2內部是異步執行。
NSLog(@"start"); NSOperationQueue *queueBlock = [[NSOperationQueue alloc] init]; NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ sleep(2); NSLog(@"op1"); }]; NSBlockOperation *op2 = [[NSBlockOperation alloc] init]; [op2 addExecutionBlock:^{//異步操作 sleep(3); NSLog(@"start"); }]; [op2 addExecutionBlock:^{ sleep(1); NSLog(@"middle"); }]; [op2 addExecutionBlock:^{ sleep(2); NSLog(@"end1"); }]; [op2 setCompletionBlock:^{ NSLog(@"op2 done"); }]; [queueBlock addOperation:op1]; [queueBlock addOperation:op2]; NSLog(@"end");執行結果: 2017-02-09 12:54:27.294 OperationTest[5105:1121668] start 2017-02-09 12:54:27.295 OperationTest[5105:1121668] end 2017-02-09 12:54:28.368 OperationTest[5105:1122096] middle 2017-02-09 12:54:29.368 OperationTest[5105:1122113] op1 2017-02-09 12:54:29.369 OperationTest[5105:1122086] end1 2017-02-09 12:54:30.370 OperationTest[5105:1122090] start 2017-02-09 12:54:30.370 OperationTest[5105:1122113] op2 done 由輸出結果可知:op1與op2之間異步執行,op2內部異步執行。
3、NSInvocationOperation
NSLog(@"start"); NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doPo:) object:@"1"]; NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doPo:) object:@"2"]; [operation start]; [operation2 start]; NSLog(@"end");輸出結果: 2017-02-09 12:58:43.835 OperationTest[5209:1144896] start 2017-02-09 12:58:47.909 OperationTest[5209:1144896] 休眠4s后 輸出參數:1 2017-02-09 12:58:51.984 OperationTest[5209:1144896] 休眠4s后 輸出參數:2 2017-02-09 12:58:51.985 OperationTest[5209:1144896] end 根據輸出結果可知,operation與operation2同步執行。
NSLog(@"start"); NSOperationQueue *queue = [[NSOperationQueue alloc] init];//直接是異步操作 NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doPo:) object:@"4"]; NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doPo:) object:@"3"]; [queue addOperation:operation]; [queue addOperation:operation2]; NSLog(@"end");輸出結果: 2017-02-09 13:01:19.211 OperationTest[5275:1160990] start 2017-02-09 13:01:19.213 OperationTest[5275:1160990] end 2017-02-09 13:01:22.287 OperationTest[5275:1161244] 休眠3s后 輸出參數:3 2017-02-09 13:01:23.288 OperationTest[5275:1161249] 休眠4s后 輸出參數:4 根據輸出結果可知:operation與operation2之間異步執行。
綜上所述:實現NSOperation的子類,實例本身調用start方法即執行同步方法,而加入執行隊列以后執行異步方法。
新聞熱點
疑難解答