- (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;
- (void)start;
一旦执行操作,就会调用target的sel方法
- (void)addOperation:(NSOperation *)op
- (void)addOperationWithBlock:(void (^)(void))block;
例子:<span style="font-size:18px;">// MARK: 单个NSInvocationOperation使用
- (void)opDemo1
{
// 1. 创建操作(典型的多态:父类指针指向子类对象)
NSOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage:) object:@"Invocation"];
// 2. 启动-- 直接在当前线程执行任务,不开启新的线程
// [op start];
// 2. 放到队列
NSOperationQueue *q = [[NSOperationQueue alloc] init];
// 只要把操作添加到队列, ---会自动异步执行调度方法
[q addOperation:op];
}
#pragma mark - 耗时操作
- (void)downloadImage:(id)obj
{
NSLog(@"%@---%@", [NSThread currentThread], obj);
}
</span>
// MARK: 多个NSInvocationOperation使用
- (void)opDemo2
{
// 队列 (GCD里面的并发(全局)队列使用最多。所以NSOperation技术直接把GCD里面的并发队列封装起来)
// NSOperationQueue队列,本质就是GCD里面的并发队列
// 操作就是GCD里面异步执行的任务
NSOperationQueue *q = [[NSOperationQueue alloc] init];
// 把多个操作放到队列
for (int i = 0 ; i < 10; i++)
{
NSOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage:) object:@"Invocation"];
// 把block操作放到队列
[q addOperation:op];
}
}
#pragma mark - 耗时操作
- (void)downloadImage:(id)obj
{
NSLog(@"%@---%@", [NSThread currentThread], obj);
}
// MARK: NSBlockOperation更简单的使用
- (void)opDemo4
{
// 队列
NSOperationQueue *q = [[NSOperationQueue alloc] init];
for (int i = 0; i < 10; i++) {
// 不创建操作对象,使用addOperationWithBlock:直接添加操作到队列
[q addOperationWithBlock:^{
NSLog(@"%@---%d", [NSThread currentThread], i);
}];
}
// 创建并添加一个 NSBlockOperation
NSBlockOperation * op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"op1 --- %@", [NSThread currentThread]);
}];
// 添加一个操作
[op1 addExecutionBlock:^{
NSLog(@"op1-1");
}];
[q addOperation:op1];
// 创建并添加一个 NSInvocationOperation
NSOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage:) object:@"Invocation"];
[q addOperation:op2];
}
#pragma mark - 耗时操作
- (void)downloadImage:(id)obj
{
NSLog(@"%@---%@", [NSThread currentThread], obj);
}
最重要的代码:
#pragma mark - 基本使用
// MARK: 线程间通信(最重要的代码)
- (void)opDemo5
{
NSOperationQueue *q = [[NSOperationQueue alloc]init];
[q addOperationWithBlock:^{
NSLog(@"耗时操作....%@", [NSThread currentThread]);
// 在主线程更新UI
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"更新UI....%@", [NSThread currentThread]);
}];
}];
}
- (NSInteger)maxConcurrentOperationCount;
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;
<span style="font-size:18px;">// MARK: 最大并发数
- (void)opDemo6
{
// 设置最大的并发数是2 (最大并发数,不是线程的数量。 而是同时执行的操作的数量)
self.opQueue.maxConcurrentOperationCount = 2;
for (int i = 0; i < 20; i++) {
NSOperation *op = [NSBlockOperation blockOperationWithBlock:^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"%@---%d", [NSThread currentThread], i);
}];
[self.opQueue addOperation:op];
}
}
</span>
队列的取消、暂停、恢复
取消队列的所有操作
- (void)cancelAllOperations;
提示:也可以调用NSOperation的- (void)cancel方法取消单个操作
- (void)setSuspended:(BOOL)b;//YES代表暂停队列,NO代表恢复队列
- (BOOL)isSuspended;
<pre name="code" class="objc"><span style="font-size:18px;">// MARK: 暂停/继续 (对队列的暂停和继续)
- (IBAction)pause
{
// 判断操作的数量,当前队列里面是不是有操作
if (self.opQueue.operationCount == 0) {
NSLog(@"没有操作");
return;
}
// 暂停继续
self.opQueue.suspended = !self.opQueue.suspended;
if (self.opQueue.suspended) { // 队列的挂起以后,队列里面的操作还在
NSLog(@"暂停");
}else{
NSLog(@"继续");
}
}
</span>
<span style="font-size:18px;">// MARK: 取消队列里的所有操作
// “取消操作,并不会影响队列的挂起状态”
- (IBAction)cancelAll
{
// 取消队列的所有操作
[self.opQueue cancelAllOperations]; // 取消队列的所有操作,会把任务从队列里面全部删除
NSLog(@"取消所有的操作");
// 取消队列的挂起状态
// (只要是取消了队列的操作,我们就把队列处于启动状态。以便于队列的继续)
self.opQueue.suspended = NO;
}
</span>
- (NSOperationQueuePriority)queuePriority;
- (void)setQueuePriority:(NSOperationQueuePriority)p;
- (void (^)(void))completionBlock;
- (void)setCompletionBlock:(void (^)(void))block;
[operationB addDependency:operationA]; // 操作B依赖于操作A
#pragma mark - 高级操作
// MARK: 依赖关系
- (void)dependecy
{
/**
例子:
1. 下载一个小说的压缩包
2. 解压缩,删除压缩包
3. 更新UI
*/
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"1. 下载一个小说的压缩包, %@",[NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"2. 解压缩,删除压缩包, %@",[NSThread currentThread]);
}];
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"3. 更新UI, %@",[NSThread currentThread]);
}];
// 指定任务之间的依赖关系 -- 依赖关系可以跨队列(可以在子线程下载完,到主线程更新UI)
[op2 addDependency:op1];
[op3 addDependency:op2];
// 注意点:一定不要出现循环依赖关系
// [op1 addDependency:op3];
// waitUntilFinished 类似GCD的调度组的通知
// NO 不等待,会直接执行 NSLog(@"come here");
// YES 等待上面的操作执行结束,再 执行 NSLog(@"come here")
[self.opQueue addOperations:@[op1, op2] waitUntilFinished:YES];
// 在主线程更新UI
[[NSOperationQueue mainQueue] addOperation:op3];
NSLog(@"come here");
}