1、NSOperation簡介
1.簡略解釋
NSOperation的作⽤:合營應用NSOperation和NSOperationQueue也能完成多線程編程
NSOperation和NSOperationQueue完成多線程的詳細步調:
(1)先將須要履行的操作封裝到一個NSOperation對象中
(2)然後將NSOperation對象添加到NSOperationQueue中
(3)體系會⾃動將NSOperationQueue中的NSOperation掏出來
(4)將掏出的NSOperation封裝的操作放到⼀條新線程中執⾏
2.NSOperation的子類
NSOperation是個籠統類,其實不具有封裝操作的才能,必需使⽤它的子類
應用NSOperation⼦類的方法有3種:
(1)NSInvocationOperation
(2)NSBlockOperation
(3)自界說子類繼續NSOperation,完成外部響應的⽅法
2、 詳細解釋
1.NSInvocationOperation子類
創立對象和履行操作:
//創立操尴尬刁難象,封裝要履行的義務
//NSInvocationOperation 封裝操作
NSInvocationOperation *operation=[[NSInvocationOperation alloc]initWithtarget:self selector:@selector(test) object:nil];
//履行操作
[operation start];
解釋:一旦執⾏操作,就會挪用target的test辦法
代碼示例:
//
// YYViewController.m
// 01-NSOperation根本1
//
// Created by 孔醫己 on 14-6-25.
// Copyright (c) 2014年 itcast. All rights reserved.
//
#import "YYViewController.h"
@interface YYViewController ()
@end
@implementation YYViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//NSOperation:籠統類,不具有封裝功效
//創立操尴尬刁難象,封裝要履行的義務
//NSInvocationOperation 封裝操作
NSInvocationOperation *operation=[[NSInvocationOperation alloc]initWithtarget:self selector:@selector(test) object:nil];
//履行操作
[operation start];
}
-(void)test
{
NSLog(@"--test--%@--",[NSThread currentThread]);
}
@end
打印檢查:
留意:操尴尬刁難象默許在主線程中履行,只要添加到隊列中才會開啟新的線程。即默許情形下,假如操作沒有放到隊列中queue中,都是同步履行。只要將NSOperation放到一個NSOperationQueue中,才會異步履行操作
2.NSBlockOperation子類
創立對象和添加操作:
//創立NSBlockOperation操尴尬刁難象
NSBlockOperation *operation=[NSBlockOperation blockOperationWithBlock:^{
//......
}];
//添加操作
[operation addExecutionBlock:^{
//....
}];
代碼示例:
代碼1:
//
// YYViewController.m
// 02-NSTherad根本2
//
// Created by 孔醫己 on 14-6-25.
// Copyright (c) 2014年 itcast. All rights reserved.
//
#import "YYViewController.h"
@interface YYViewController ()
@end
@implementation YYViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//創立NSBlockOperation操尴尬刁難象
NSBlockOperation *operation=[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"NSBlockOperation------%@",[NSThread currentThread]);
}];
//開啟履行操作
[operation start];
}
@end
打印檢查:
代碼2:
//
// YYViewController.m
// 02-NSTherad根本2
//
// Created by 孔醫己 on 14-6-25.
// Copyright (c) 2014年 itcast. All rights reserved.
//
#import "YYViewController.h"
@interface YYViewController ()
@end
@implementation YYViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//創立NSBlockOperation操尴尬刁難象
NSBlockOperation *operation=[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"NSBlockOperation------%@",[NSThread currentThread]);
}];
//添加操作
[operation addExecutionBlock:^{
NSLog(@"NSBlockOperation1------%@",[NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"NSBlockOperation2------%@",[NSThread currentThread]);
}];
//開啟履行操作
[operation start];
}
@end
留意:只需NSBlockOperation封裝的操作數 > 1,就會異步履行操作
3.NSOperationQueue
NSOperationQueue的作⽤:NSOperation可以調⽤start⽅法來執⾏義務,但默許是同步履行的
假如將NSOperation添加到NSOperationQueue(操作隊列)中,體系會主動異步履行NSOperation中的操作
添加操作到NSOperationQueue中,主動履行操作,主動開啟線程
//創立NSOperationQueue
NSOperationQueue * queue=[[NSOperationQueue alloc]init];
//把操作添加到隊列中
//第一種方法
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
//第二種方法
[queue addOperationWithBlock:^{
NSLog(@"NSBlockOperation3--4----%@",[NSThread currentThread]);
}];
- (void)addOperation:(NSOperation *)op;
- (void)addOperationWithBlock:(void (^)(void))block;
代碼示例:
//
// YYViewController.m
// 03-NSOperation根本3
//
// Created by 孔醫己 on 14-6-25.
// Copyright (c) 2014年 itcast. All rights reserved.
//
#import "YYViewController.h"
@interface YYViewController ()
@end
@implementation YYViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//創立NSInvocationOperation對象,封裝操作
NSInvocationOperation *operation1=[[NSInvocationOperation alloc]initWithtarget:self selector:@selector(test1) object:nil];
NSInvocationOperation *operation2=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test2) object:nil];
//創立對象,封裝操作
NSBlockOperation *operation3=[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"NSBlockOperation3--1----%@",[NSThread currentThread]);
}];
[operation3 addExecutionBlock:^{
NSLog(@"NSBlockOperation3--2----%@",[NSThread currentThread]);
}];
//創立NSOperationQueue
NSOperationQueue * queue=[[NSOperationQueue alloc]init];
//把操作添加到隊列中
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
}
-(void)test1
{
NSLog(@"NSInvocationOperation--test1--%@",[NSThread currentThread]);
}
-(void)test2
{
NSLog(@"NSInvocationOperation--test2--%@",[NSThread currentThread]);
}
@end
打印後果:
留意:體系主動將NSOperationqueue中的NSOperation對象掏出,將其封裝的操作放到一條新的線程中履行。下面的代碼示例中,一共有四個義務,operation1和operation2分離有一個義務,operation3有兩個義務。一共四個義務,開啟了四條線程。經由過程義務履行的時光全體都是273可以看出,這些義務是並行履行的。
提醒:隊列的掏出是有次序的,與打印成果其實不抵觸。這就比如,選手A,BC固然起跑的次序是先A,後B,然後C,然則達到起點的次序卻紛歧定是A,B在前,C在後。
上面應用for輪回打印,可以更顯著的看出義務是並發履行的。
代碼示例:
#import "YYViewController.h"
@interface YYViewController ()
@end
@implementation YYViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//創立NSInvocationOperation對象,封裝操作
NSInvocationOperation *operation1=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test1) object:nil];
NSInvocationOperation *operation2=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test2) object:nil];
//創立對象,封裝操作
NSBlockOperation *operation3=[NSBlockOperation blockOperationWithBlock:^{
for (int i=0; i<5; i++) {
NSLog(@"NSBlockOperation3--1----%@",[NSThread currentThread]);
}
}];
[operation3 addExecutionBlock:^{
for (int i=0; i<5; i++) {
NSLog(@"NSBlockOperation3--2----%@",[NSThread currentThread]);
}
}];
//創立NSOperationQueue
NSOperationQueue * queue=[[NSOperationQueue alloc]init];
//把操作添加到隊列中
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
}
-(void)test1
{
for (int i=0; i<5; i++) {
NSLog(@"NSInvocationOperation--test1--%@",[NSThread currentThread]);
}
}
-(void)test2
{
for (int i=0; i<5; i++) {
NSLog(@"NSInvocationOperation--test2--%@",[NSThread currentThread]);
}
}
@end
3、並發數
(1)並發數:同時執⾏行的義務數.好比,同時開3個線程履行3個義務,並發數就是3
(2)最年夜並發數:統一時光最多只能履行的義務的個數。
(3)最⼤年夜並發數的相干⽅辦法
- (NSInteger)maxConcurrentOperationCount;
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;
解釋:假如沒有設置最年夜並發數,那末並發的個數是由體系內存和CPU決議的,能夠內存多久開多一點,內存少就開少一點。
留意:num的值其實不代表線程的個數,僅僅代表線程的ID。
提醒:最年夜並發數不要亂寫(5之內),不要開太多,普通以2~3為好,由於固然義務是在子線程停止處置的,然則cpu處置這些過量的子線程能夠會影響UI,讓UI變卡。
4、隊列的撤消,暫停和恢復
(1)撤消隊列的一切操作
- (void)cancelAllOperations;
提⽰:也能夠挪用NSOperation的- (void)cancel⽅法撤消單個操作
(2)暫停和恢復隊列
- (void)setSuspended:(BOOL)b; // YES代表暫停隊列,NO代表恢復隊列
- (BOOL)isSuspended; //以後狀況
(3)暫停和恢復的實用場所:在tableview界面,開線程下載長途的收集界面,對UI會有影響,應用戶體驗變差。那末這類情形,便可以設置在用戶操作UI(如轉動屏幕)的時刻,暫停隊列(不是撤消隊列),停滯轉動的時刻,恢復隊列。
5、操作優先級
(1)設置NSOperation在queue中的優先級,可以轉變操作的執⾏優先級
- (NSOperationQueuePriority)queuePriority;
- (void)setQueuePriority:(NSOperationQueuePriority)p;
(2)優先級的取值
NSOperationQueuePriorityVeryLow = -8L,
NSOperationQueuePriorityLow = -4L,
NSOperationQueuePriorityNormal = 0,
NSOperationQueuePriorityHigh = 4,
NSOperationQueuePriorityVeryHigh = 8
解釋:優先級高的義務,挪用的概率會更年夜。
6、操作依附
(1)NSOperation之間可以設置依附來包管履行次序,⽐如必定要讓操作A履行完後,能力履行操作B,可以像上面這麼寫
[operationB addDependency:operationA]; // 操作B依附於操作
(2)可以在分歧queue的NSOperation之間創立依附關系
留意:不克不及輪回依附(不克不及A依附於B,B又依附於A)。
(3)代碼示例
#import "YYViewController.h"
@interface YYViewController ()
@end
@implementation YYViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//創立NSInvocationOperation對象,封裝操作
NSInvocationOperation *operation1=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test1) object:nil];
NSInvocationOperation *operation2=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(test2) object:nil];
//創立對象,封裝操作
NSBlockOperation *operation3=[NSBlockOperation blockOperationWithBlock:^{
for (int i=0; i<5; i++) {
NSLog(@"NSBlockOperation3--1----%@",[NSThread currentThread]);
}
}];
[operation3 addExecutionBlock:^{
for (int i=0; i<5; i++) {
NSLog(@"NSBlockOperation3--2----%@",[NSThread currentThread]);
}
}];
//設置操作依附
//先履行operation2,再履行operation1,最初履行operation3
[operation3 addDependency:operation1];
[operation1 addDependency:operation2];
//不克不及是互相依附
// [operation3 addDependency:operation1];
// [operation1 addDependency:operation3];
//創立NSOperationQueue
NSOperationQueue * queue=[[NSOperationQueue alloc]init];
//把操作添加到隊列中
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
}
-(void)test1
{
for (int i=0; i<5; i++) {
NSLog(@"NSInvocationOperation--test1--%@",[NSThread currentThread]);
}
}
-(void)test2
{
for (int i=0; i<5; i++) {
NSLog(@"NSInvocationOperation--test2--%@",[NSThread currentThread]);
}
}
@end
打印檢查:
A做完再做B,B做完才做C。
留意:必定要在添加上前,停止設置。
提醒:義務添加的次序其實不可以或許決議履行次序,履行的次序取決於依附。應用Operation的目標就是為了閃開發人員不再關懷線程。
5.操作的監聽
可以監聽一個操作的履行終了
- (void (^)(void))completionBlock;
- (void)setCompletionBlock:(void (^)(void))block;
代碼示例
第一種方法:可以直接跟在義務前面編寫須要完成的操作,如這裡鄙人載圖片後,緊隨著下載第二張圖片。然則這類寫法有的時刻把兩個不相干的操作寫到了一個代碼塊中,代碼的可浏覽性不強。
#import "YYViewController.h"
@interface YYViewController ()
@end
@implementation YYViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//創立對象,封裝操作
NSBlockOperation *operation=[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"-operation-下載圖片-%@",[NSThread currentThread]);
//.....下載圖片後持續停止的操作
NSLog(@"--接著下載第二張圖片--");
}];
//創立隊列
NSOperationQueue *queue=[[NSOperationQueue alloc]init];
//把義務添加到隊列中(主動履行,主動開線程)
[queue addOperation:operation];
}
@end
第二種方法:
#import "YYViewController.h"
@interface YYViewController ()
@end
@implementation YYViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//創立對象,封裝操作
NSBlockOperation *operation=[NSBlockOperation blockOperationWithBlock:^{
for (int i=0; i<10; i++) {
NSLog(@"-operation-下載圖片-%@",[NSThread currentThread]);
}
}];
//監聽操作的履行終了
operation.completionBlock=^{
//.....下載圖片後持續停止的操作
NSLog(@"--接著下載第二張圖片--");
};
//創立隊列
NSOperationQueue *queue=[[NSOperationQueue alloc]init];
//把義務添加到隊列中(主動履行,主動開線程)
[queue addOperation:operation];
}
@end
打印檢查:
解釋:在上一個義務履行完後,會履行operation.completionBlock=^{}代碼段,且是在以後線程履行(2)。
【iOS多線程運用開辟中應用NSOperation類的根本辦法】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!