在iOS开发中,我们始终无法避开多线程的使用。在Foundation框架中,使用c写的GCD是我们一般使用最频繁的,但却不是最系统的。在GCD的基础上,Apple对其封装了一层也就是NSOperation这个类,它有很多的方法和机制可以使用,大大的方便了我们的开发。在学习中,我们尽可能先熟悉并掌握高级别的api,之后再去熟悉并掌握其底层的封装。所以,今天就先说说NSOperation。
1.NSOperation不能直接使用
NSOperation这个类是抽象类,一般使用它的子类。
它的内部属性和方法:
- (void)start;// 要么start, 要么放进队列里,开始执行。同样的效果。
- (void)main;
@property (readonly, getter=isCancelled) BOOL cancelled;
- (void)cancel; // 和start或者放进队列开始执行相对,取消执行。
@property (readonly, getter=isExecuting) BOOL executing;
@property (readonly, getter=isFinished) BOOL finished;
@property (readonly, getter=isConcurrent) BOOL concurrent;
@property (readonly, getter=isAsynchronous) BOOL asynchronous
@property (readonly, getter=isReady) BOOL ready;
- (void)addDependency:(NSOperation *)op;
- (void)removeDependency:(NSOperation *)op;
@property (readonly, copy) NSArray *dependencies;
@property NSOperationQueuePriority queuePriority;
@property (nullable, copy) void (^completionBlock)(void) API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
- (void)waitUntilFinished API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
@property double threadPriority API_DEPRECATED("Not supported", macos(10.6,10.10), ios(4.0,8.0), watchos(2.0,2.0), tvos(9.0,9.0));
@property NSQualityOfService qualityOfService API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
@property (nullable, copy) NSString *name API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
系统的api里有两个其两个子类: NSBlockOperation 和 NSInvocationOperation,当然也可以自定义子类继承NSOperation,实现内部相应的方法。
NSBlockOperation 和 NSInvocationOperation的最大却别就在于,一个是block回调结构,另一个是target的结构模式。基于结构上的基本差别,也就带来了很多其他的细节上的结构区别。
2.NSBlockOperation的使用
NSBlockOperation的方法和属性。
+ (instancetype)blockOperationWithBlock:(void (^)(void))block;
- (void)addExecutionBlock:(void (^)(void))block;
@property (readonly, copy) NSArray *executionBlocks;
例子:👇
初始化了一个NSBlockOperation对象,用一个Block来封装需要执行的操作。 再调用start方法,紧接着会马上执行Block中的内容,这里还是在当前线程同步执行操作,并没有异步执行,阻塞主线程。

要想实现多个任务的操作,就得需要使用addOperation的方法:例如:

当然,父类还有很多方法可以使用。
3.NSInvocationOperation的使用
它的方法和属性:
- (nullable instancetype)initWithTarget:(id)target selector:(SEL)sel object:(nullable id)arg;
- (instancetype)initWithInvocation:(NSInvocation *)inv NS_DESIGNATED_INITIALIZER;
@property (readonly, retain) NSInvocation *invocation;
@property (nullable, readonly, retain) id result;// 执行结果
例子:👇
它不能像NSBlockOperation一样能够添加多个执行,所以用的较少。

4.NSOperationQueue的使用
系统的子类中只有NSBlockOperation可以添加多个执行的代码块,那么在实际开发中,我们会有狠多操作之间的依赖问题,来处理这个问题的类就是继承自NSObject的NSOperationQueue!
它的方法和属性:
- (void)addOperation:(NSOperation *)op;// 添加一个操作
- (void)addOperations:(NSArray *)ops waitUntilFinished:(BOOL)wait;// 添加一个操作的数组
- (void)addOperationWithBlock:(void (^)(void))block ;// 添加一个操错的block
@property (readonly, copy) NSArray<__kindof NSOperation *> *operations;//所有的操作的数组
@property (readonly) NSUInteger operationCount;// 操作的个数
@property NSInteger maxConcurrentOperationCount;//操作的最大并发数目
@property (getter=isSuspended) BOOL suspended;//是否暂停
@property (nullable, copy) NSString *name;// 队列的名字
@property NSQualityOfService qualityOfService;// 服务的质量
@property (nullable, assign /* actually retain */) dispatch_queue_t underlyingQueue;// 优先队列
- (void)cancelAllOperations;// 取消所有的操作
- (void)waitUntilAllOperationsAreFinished;// 当所有的操作结束时候调用的方法
@property (class, readonly, strong, nullable) NSOperationQueue *currentQueue;// 当前队列
@property (class, readonly, strong) NSOperationQueue *mainQueue;// 主队列
例子:

和GCD的栅栏效果一样,都是异步的串行效果。