美文网首页
iOS NSOperation 源码分析原理

iOS NSOperation 源码分析原理

作者: 孙掌门 | 来源:发表于2019-12-19 21:09 被阅读0次

iOS NSOperation 源码分析原理

特性

1.添加任务依赖
2.任务执行状态的控制
3.设置操作的优先级
4.设置最大并发量
5.可以取消一个操作
6.使用 KVO 观察对操作执行状态的更改:isExecuteing、isFinished、isCancelled

任务状态的控制

1.isReady

2.isExecuting

3.isFinished

4.isCancelled

5.如果我们重写main方法,底层会为我们控制任务的执行状态,以及任务的退出

6.如果我们重写start,需要自己控制任务状态。

源码分析 (gnustep-base-1.26.0 版本)

我们下载gnustep-base-1.26.0的源码,然后找到 NSOperation.m,文件,然后会看到有start方法

- (void) start
{
  NSAutoreleasePool *pool = [NSAutoreleasePool new];
  double        prio = [NSThread  threadPriority];

  AUTORELEASE(RETAIN(self));    // Make sure we exist while running.
  [internal->lock lock];
  NS_DURING
    {
      if (YES == [self isExecuting])
    {
      [NSException raise: NSInvalidArgumentException
              format: @"[%@-%@] called on executing operation",
        NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
    }
      if (YES == [self isFinished])
    {
      [NSException raise: NSInvalidArgumentException
              format: @"[%@-%@] called on finished operation",
        NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
    }
      if (NO == [self isReady])
    {
      [NSException raise: NSInvalidArgumentException
              format: @"[%@-%@] called on operation which is not ready",
        NSStringFromClass([self class]), NSStringFromSelector(_cmd)];
    }
      if (NO == internal->executing)
    {
      [self willChangeValueForKey: @"isExecuting"];
      internal->executing = YES;
      [self didChangeValueForKey: @"isExecuting"];
    }
    }
  NS_HANDLER
    {
      [internal->lock unlock];
      [localException raise];
    }
  NS_ENDHANDLER
  [internal->lock unlock];

  NS_DURING
    {
      if (NO == [self isCancelled])
    {
      [NSThread setThreadPriority: internal->threadPriority];
      [self main];
    }
    }
  NS_HANDLER
    {
      [NSThread setThreadPriority:  prio];
      [localException raise];
    }
  NS_ENDHANDLER;

  [self _finish];
  [pool release];
}

我们来分析下,首先我们可以看到,创建了一个 autoReleasePool,然后获取线程的优先级,接着加了锁,接着是一堆判断,我们先不关心,然后我们可以看到

 if (NO == internal->executing)
    {
      [self willChangeValueForKey: @"isExecuting"];
      internal->executing = YES;
      [self didChangeValueForKey: @"isExecuting"];
    }

如果当前没有在执行,则通过 KVO 的方式来通知当前正在执行了,什么事KVO,可以看我之前的文章,接下来


  if (NO == [self isCancelled])
    {
      [NSThread setThreadPriority: internal->threadPriority];
      [self main];
    }

这里,判断如果没有取消,那么久执行main函数,然后我们看下 main 函数

- (void) main;
{
  return;   // OSX default implementation does nothing
}

所以从源码可以看出,我们只需要重写 main 函数来执行我们的任务就行了,再接着往下看

[self _finish];


这个finish做了什么呢?


- (void) _finish
{
  /* retain while finishing so that we don't get deallocated when our
   * queue removes and releases us.
   */
  [self retain];
  [internal->lock lock];
  if (NO == internal->finished)
    {
      if (YES == internal->executing)
        {
      [self willChangeValueForKey: @"isExecuting"];
      [self willChangeValueForKey: @"isFinished"];
      internal->executing = NO;
      internal->finished = YES;
      [self didChangeValueForKey: @"isFinished"];
      [self didChangeValueForKey: @"isExecuting"];
    }
      else
    {
      [self willChangeValueForKey: @"isFinished"];
      internal->finished = YES;
      [self didChangeValueForKey: @"isFinished"];
    }
      if (NULL != internal->completionBlock)
    {
      CALL_BLOCK_NO_ARGS(internal->completionBlock);
    }
    }
  [internal->lock unlock];
  [self release];
}

这段代码很容易理解,就是通过KVO来设置 executing 为 NO, finished 为YES。

所以从上面 NSOperation.m 的源码可以看出,如果我们重写了 Main ,系统会为我们设置一系列的属性,并且通过KVO通知,但是如果我们重写了Stat方法,相当于,重写了上面的源码,所以任何属性的控制都需要我么自己来控制

系统是怎么帮我们从 NSOperationQueue中移除任务的呢?

上面我们已经说了,系统帮我们控制了属性的变更,通过KVO,那么NSOperationQueue,就一定是通过监听KVO来做到的,我们通过查看源码,果然,在下面 有个分类


@implementation NSOperationQueue (Private)

- (void) observeValueForKeyPath: (NSString *)keyPath
               ofObject: (id)object
                         change: (NSDictionary *)change
                        context: (void *)context

并且监听了KVO,系统就是在这个方法里面为我们移除任务的

通过对源码的分析,是不是豁然开朗了?

相关文章

网友评论

      本文标题:iOS NSOperation 源码分析原理

      本文链接:https://www.haomeiwen.com/subject/lxmvnctx.html