IOS intermediate -- multithreading -- NSOperation, ios -- nsoperation
The NSOperation operation task encapsulates the code and the operation encapsulates the task. The purpose is to pause, resume, and cancel the task at any time;
NSOperation encapsulation of GCD. OC is more convenient to use. abstract class. Car
Use of NSOperation:
<1> the start method is directly called for an operation, except when the number of tasks encapsulated in the Block is greater than 1 ).
<2> put the operation in the queue. The thread is automatically enabled to execute the operation.
Two subclasses:
NSInvocationOperation: Call 1. use of two NSOperation subclasses: // create a NSOpertation subclass NSInvocationOperation * op1 = [[NSInvocationOperation alloc] OPERATOR: self selector: @ selector (longTimeOperation) object: nil]; [op1 start]; // The call start task does not enable the thread. Run NSBlockOperation: Block // in the main thread to create an NSOpertation subclass NSBlockOperation * op2 = [NSBlockOperation blockOperationWithBlock: ^ {
// Encapsulate the operation in the Block.
[Self longTimeOperation] ;}]; // append an operation (task ). [op2 addExecutionBlock: ^ {NSLog (@ "Download image 1: % @", [NSThread currentThread]) ;}]; // append an operation (task ). [op2 addExecutionBlock: ^ {NSLog (@ "Download Image 2: % @", [NSThread currentThread]) ;}]; // [op2 start]; // NSBlockOperation directly calls the start method: // if there is only one task: run in the main thread // If there are multiple tasks: multiple threads will be enabled, tasks are executed in both the main thread and sub-threads. // multiple tasks are executed simultaneously.
// Callback after the operation is completed (asynchronous callback)
// It is rarely used.
Op2.completionBlock = ^ {
// Callback after the operation is completed (we do not know when the operation is completed)
NSLog (@ "Operation 1 completed % @", [NSThreadcurrentThread]) ;}; // create a non-queue: Non-main queue column: operations for storing non-main columns are all performed in the sub-main thread. NSOperationQueue * queue = [[NSOperationQueue alloc] init]; // obtain a main queue column. The main queue column stores NSOperationQueue * mainQueue = [NSOperationQueue mainQueue] in the main thread. // use: add the operation to the queue [queue addOperation: op2]; [queue addOperation: op1]; // Add the operation to the queue automatically (enable the thread). add a task to the queue. Call the main method in Operation. Then the task is automatically executed.
Task dependency [op1 addDependency: op2]; // After op2 is executed, op1 [op2 addDependency: op3] is executed. // The result of executing the op2 statement after op3 is executed is: op3 first executes the op1 advanced operation on op2: in general, queues are implemented using the method of lazy loading @ property (nonatomic, strong) NSOperationQueue * queue; // The Queue is loaded lazily.
-(NSOperationQueue *) queue
{
If (! _ Queue ){
_ Queue = [[NSOperationQueuealloc] init];
// The maximum concurrency is 6.
[_ QueuesetMaxConcurrentOperationCount: 6];
}
Return_queue;} All self used in the block must use the weak method. Otherwise, a circular reference problem will occur. _ weaktypeof (self) wself = self; NSBlockOperation * op2 = [NSBlockOperation blockOperationWithBlock: ^ {[wself longTimeOperation] ;}]; // cancels a single operation, which is generally not required. [op2 cancel]; // pause operations in the queue [self. queue setsuincluded: YES]; // restore the operation in the queue [self. queue setsuincluded: NO]; // cancel all operations. For canceled operations, they will be permanently canceled and will not be enabled again [self. queue cancelAllOperations];
// Custom NSOperation; NSBlockOperation * op = [NSBlockOperationblockOperationWithBlock: ^ {
// Executed task
UIImage * image = [selflongTimeOperation];
NSBlockOperation * op = [NSBlockOperationblockOperationWithBlock: ^ {self. imageView. image = image;}]; [[NSOperationQueue mainQueue] addOperation: op] ;}]; The following are three methods for custom NSOperation Methods // communication between different objects. 1. notification 1.> // send a notification when downloading the image (the parameter in the notification is image) [[nsicationicationcenter defacenter center] postNotificationName: @ "ITDownloadImageOperation" object: image];
2.> // register the notification recipient in the class of the content to be used. [[nsicationcenter center defacenter center] addObserver: self selector: @ selector (setUpImage :) name: @ "ITDownloadImageOperation" object: nil]; 3.> // The parameter passed by the notification is always an NSNotification; the method used when registering the notification-(void) setUpImage :( NSNotification *) y {// return to the main thread dispatch_async (dispatch_get_main_queue (), ^ {NSLog (@ "setUpImage % @", [NSThread currentThread]); // y. an object is the object of notification transmission. // In this notification, the object passed by the notification is the operation ITDownloadImageOperation * op = policy. object; self. imageView. image = op. image ;}) ;}2. the proxy works exactly the same as before.
3. block // 1. define a block type parameter as imagetypedefvoid (^ downloadImageOperationBlock) (UIImage * image); // 2. define the attributes of a Block @ property (nonatomic, copy) downloadImageOperationBlock downBlock; // 3. set the content to be executed in the Block; // The Block is just a Block code. when to execute the content in the Block, and define the content separately. op. downBlock = ^ (UIImage * image) {// content to be executed in the Block. self. imageView. image = image;}; // 4. execute this Block-(void) main {@ autoreleasepool {// download the image UIImage * image = [self downloadImage] in the sub-thread; // return to the main thread [[NSOperationQueue mainQueue] addOperationWithBlock: ^ {if (self. downBlock) {self. downBlock (image); NSLog (@ "content in the execution Block: set image") ;}}] ;}} 3. the block Method forms a leaflet object. For example, the first two steps of UIImage are the same as those above. // 3. define a method to pass the Block // (downloadImageOperationBlock) blk: Pass the Block as a parameter-(void) setUpImageWithBlock :( downloadImageOperationBlock) blk; // 4. implement this method, self. downBlock value-(void) setUpImageWithBlock :( downloadImageOperationBlock) blk {if (blk) {// to self. downBlock value assignment (method executed inside the Block) self. downBlock = blk;} // 5. the content in the Block is a parameter [op setUpImageWithBlock: ^ (UIImage * image) {// defines the content executed in a Block. self. imageView. image = image;}]; // 6. the call block is the same as step 3 above. the block method uses the same method as the leaflet object. Only self is passed when bolck is called. downBlock (image); Use the object when setting the value. an object ITDownloadOperationBlock * op = [[ITDownloadOperationBlockalloc] init]; [op setUpImageWithBlock: ^ (ITDownloadOperationBlock * op) {self. imageView. image = op. image;}];