NSOperation, NSOperationQueue, NSOperation queue, NSOperationQueue, NSOperationQueue, NSOperationQueue If you still have any questions about the basic knowledge of NSOperation, you can click on the above article to help you out.

NSOperation and NSOperationQueue are resolved

Why use NSOperation? NSOperation provides the encapsulation of tasks, and NSOperationQueue, as its name implies, provides the execution queue, which can automatically implement multi-core parallel computing and automatically manage the life cycle of threads. If it is concurrent, its bottom layer also uses the thread pool model to manage. Basically, it can be said that the functions provided by these two classes cover GCD. It also provides more customizable development methods that developers can choose on demand. NSOperation assigns the encapsulated tasks to different NSOperationQueues for serial or concurrent queue execution. Normally, the task is given to a method of the NSOperation class, the main or start method, so if we want to customize the inheritance of the NSOperation class, we need to override the related method.

NSOperationCommon properties and methods

Rewriting method

- (void)start; // Non-concurrent operations need to override this method - (void)main;Copy the code

Relevant properties

// Whether the task cancels (read only) custom subclasses, override @property (readonly, getter=isCancelled) BOOL cancelled; '// isCancelled' (void)cancel; // isCancelled (void)cancel; // Whether the task is executing (read only), custom subclass, override @property (readonly, getter=isExecuting) BOOL executing; // If YES, the queue will remove the task from the queue @property (readonly, getter=isFinished) BOOL finished; // If the task is concurrent (read-only), the default return is NO // custom subclass, override the getter method, and return yes@property (readonly, getter=isAsynchronous) BOOL asynchronous; // For queued tasks, ready is YES, indicating that the task is about to be executed. // If dependent tasks are not completed, ready is no@property (readonly, getter=isReady) BOOL ready;
Copy the code

Synchronous operation

// add task dependency - (void)addDependency:(NSOperation *)op; // remove task dependency - (void)removeDependency:(NSOperation *)op; typedef NS_ENUM(NSInteger, NSOperationQueuePriority) { NSOperationQueuePriorityVeryLow = -8L, NSOperationQueuePriorityLow = -4L, NSOperationQueuePriorityNormal = 0, NSOperationQueuePriorityHigh = 4, NSOperationQueuePriorityVeryHigh = 8 }; // The priority of the task in the queue @property NSOperationQueuePriority queuePriority; // completionBlock @property (nullable, copy) void (^completionBlock)(void); // completionBlock @property (nullable, copy) void (^completionBlock)(void); // Block the current thread until the operation ends, which can be used for sequential synchronization of threads - (void)waitUntilFinished;
Copy the code

NSOperationQueueCommon properties and methods

Add tasks

// add a task to queue - (void)addOperation:(NSOperation *)op; // Add an array of operations to the queue,waitFlag whether to block the current thread until all operations are complete - (void)addOperations:(NSArray<NSOperation *> *)opswaitUntilFinished:(BOOL)wait; // Add a block action object to the queue. - (void)addOperationWithBlock:(void (^)(void))block;Copy the code

Relevant properties

// Get all tasks in the queue (read only) @property (readonly, copy) NSArray<__kindof NSOperation *> *operations; // Get the number of tasks in the queue (read only) @property (readonly) NSUInteger operationCount; / / the biggest task queue to support concurrency @ property NSInteger maxConcurrentOperationCount; // whether the queue isSuspended @property (getter=isSuspended) BOOL suspended; @property (nullable, copy) NSString *nameCopy the code

Relevant methods

Void cancelAllOperations; void cancelAllOperations; // Block the current thread until all tasks are completed - (void)waitUntilAllOperationsAreFinished; @property (class,readonly, strong, nullable) NSOperationQueue *currentQueue; @property (class,readonly, strong) NSOperationQueue *mainQueue;

Copy the code

Custom NSOperation subclass

There are two ways to customize NSOperation subclasses in official documentation, concurrent and non-concurrent. Non-concurrent only need to inherit NSOperation, implement the main method. Concurrent operations are relatively more common, as described below.

A non-concurrent NSOperation subclass

Description: Methods to Override For non-concurrent operations, you typically Override only one method: main Into this method, you place the code needed to perform the given task.

In the official document, it is pointed out that the non-concurrent task, directly put the task to be executed in the main method, and then directly call. The finished property is not implemented. After obtaining the FINISHED property, only NO is returned. The finished task will not be deleted after it is queued. Also, there is no need to use this non-concurrent NSOperation subclass, because I can’t think of a scenario where I would need to use it because it’s inconvenient.

Concurrent NSOperation subclass

Official document Description: Methods to Override If you are creating a concurrent operation, you need to override the following methods and properties at a minimum: start asynchronous executing finished

As you can see from the official documentation, the following methods or attributes need to be overridden to implement a custom subclass of concurrency:

  • start: Put the tasks that need to be performed instartMethod, when a task is added to a queue, the queue manages the task and calls it when the thread is scheduledstartMethod, without calling the parent class’s methods
  • asynchronous: Indicates whether to execute concurrently
  • executing: indicates whether a task is being executed. You need to manually call the KVO method to notify other classes of monitoring the task
  • finished: indicates whether the task is over. You need to manually invoke the KVO method to notify the task. The queue also needs to listen to the value of the modified attribute to determine whether the task is over

Related codes:

@interface ZBOperation : NSOperation @property (nonatomic, readwrite, getter=isExecuting) BOOL executing; @property (nonatomic, readwrite, getter=isFinished) BOOL finished; @end@implementation ZBOperation // Since the parent class is Readonly, we need to manually synthesize setters if we need them when we overload. @synthesize executing = _executing; @synthesize finished = _finished; - (void)start { @autoreleasepool{ self.executing = YES;if (self.cancelled) {
            [self done];
            return; } // Task... } // When the task is completed, manually set the status [self]done];
}

- (void)done {
    self.finished = YES;
    self.executing = NO;
}

#pragma mark - setter -- getter
- (void)setKVO (BOOL) {// Call self willChangeValueForKey:@"isExecuting"]; _executing = executing; // Call the KVO notification [self didChangeValueForKey:@"isExecuting"];
}

- (BOOL)isExecuting {
    return _executing;
}

- (void)setFinished:(BOOL)finished {
    if(_finished ! = finished) { [self willChangeValueForKey:@"isFinished"];
        _finished = finished;
        [self didChangeValueForKey:@"isFinished"];
    }
}

- (BOOL)isFinished {
    return_finished; } // Return YES for concurrent Operation - (BOOL)isAsynchronous {returnYES; } // Call class - (void)congfigOperation {self.queue = [[NSOperationQueue alloc] init]; [self.queuesetMaxConcurrentOperationCount:2];
    
    self.zbOperation = [[ZBOperation alloc] init];
    [self.queue addOperation:self.zbOperation];
}
Copy the code

The use of custom subclasses of NSOperation and NSOperationQueue is basically described, but you can refer to the official documentation for more details.

For NSOperation and NSOperationQueue applications, we can read the source code for AFNetworking and SDWebImage, which uses a lot of NSOperation operations.