Multithreading technology for iOS development-NSOperation, iosnsoperation

Source: Internet
Author: User

Multithreading technology for iOS development-NSOperation, iosnsoperation

This article describes the NSOperation Technology Used in iOS development from four aspects:

1. What is NSOperation 2. Why do we use NSOperation 3. How to Use NSOperation in actual development 1. Custom NSOperation 2. Basic use of NSOperation 3. NSOperation for inter-thread Communication

    1) use a proxy for message transmission

    2) use notifications for message transmission

    3) Use block for message transmission

Iv. Comparison with GCD 1. What is NSOperation?

NSOperation is an abstract base class that represents an Independent Computing Unit. It can provide useful and thread-safe creation, priority, dependency, and cancellation operations for child classes. The system has encapsulated the NSBlockOperation and NSInvocationOperation entity classes for us. It is also very simple to use, but we are more likely to inherit and customize our own operations.

 

Ii. Why do we use NSOperation?

In iOS development, to improve user experience, we usually place time-consuming operations outside the main thread for processing. For normal simple operations, we choose GCD with less code, so that we can focus on our own business logic development. NSOperation is also implemented based on GCD after ios4, but it is more controllable than GCD and can be added with operational dependencies.

 

3. How to Use NSOperation1 and custom NSOperation in actual development

In actual development, the NSOperation provided by the system may not meet our needs. In this case, we need to customize our own NSOperation.

@ Interface ViewController () @ property (nonatomic, weak) IBOutlet UIImageView * imageView; @ end @ implementation ViewController-(void) touchesBegan :( NSSet <UITouch *> *) touches withEvent :( UIEvent *) event {NSLog (@ "touchesBegan ------ % @", [NSThread currentThread]); if (! Self. imageView. image) {// avoid repeated downloads and enhance user experience NSOperationQueue * queue = [[NSOperationQueue alloc] init]; [queue setMaxConcurrentOperationCount: 6]; myOperation * myO = [[MyOperation alloc] init]; myO. imageView = self. imageView; [queue addOperation: myO];} NSLog (@ "end");} // custom NSOperation @ interface MyOperation: NSOperation @ property (nonatomic, strong) UIImageView * imageView; @ end // implement custom NSOperation @ implementation MyOperation-(void) main {NSLog (@ "% s ---- % @", _ func __, [NSThread currentThread]); UIImage * image = [self downLoadImage: @ "http://g.hiphotos.baidu.com/image/pic/item/f31fbe096b63f624cd2991e98344ebf81b4ca3e0.jpg"]; dispatch_async (dispatch_get_main_queue (), ^ {NSLog (@ "% =====%@", image, [NSThread currentThread]); self. imageView. image = image;}) ;}- (UIImage *) downLoadImage :( NSString *) urlString {NSLog (@ "% s ---- % @" ,__ func __, [NSThread currentThread]); NSURL * url = [NSURL URLWithString: urlString]; NSData * data = [NSData dataWithContentsOfURL: url]; UIImage * image = [UIImage imageWithData: data]; NSLog (@ "image downloaded"); return image ;}@ end

 

 

2. Basic use of NSOperation
# Pragma mark-NSOperation advanced operation 1-(void) highLevelTest1 {/** NSOperation adds the following management thread functions compared with GCD: 1. NSOperation can be used to add operation dependencies: ensure the operation execution sequence! --> It is the same as adding a task to a serial queue in GCD! A serial queue corresponds to the sequential execution (Serial Queue) in a thread GCD ---> after the serial execution adds operation dependencies, the system may perform the serial execution to ensure the task execution sequence, it is also possible that the green thread synchronization technology ensures the task execution sequence */NSInvocationOperation * inO = [[NSInvocationOperation alloc] initWithTarget: self selector: @ selector (test) object: nil]; NSBlockOperation * block1 = [NSBlockOperation blockOperationWithBlock: ^ {NSLog (@ "block1 =======%@", [NSThread currentThread]);}]; NSBlockOperation * block2 = [NSBlockOperation blockOperationW IthBlock: ^ {NSLog (@ "block2 =====%@", [NSThread currentThread]) ;}]; NSBlockOperation * block3 = [NSBlockOperation blockOperationWithBlock: ^ {NSLog (@ "block3 =====%@", [NSThread currentThread]) ;}];/** the four operations are time-consuming operations, in addition, operations must be performed in sequence. Operation 2 is the note for adding operation dependencies for UI operations. you must add operation dependencies before adding operations to the operation queue. do not add cyclic dependency. Advantages: The operation dependency is still valid for operations in different operation queues * // 1. be sure to add the operation dependency [block2 addDependency: block1]; [block3 addDependency: block2]; [in O addDependency: block3]; // 2. do not add circular dependencies [block1 addDependency: block3]; [[[NSOperationQueue alloc] init] addOperation: block1]; [[[NSOperationQueue alloc] init] addOperation: block2]; [[NSOperationQueue alloc] init] addOperation: block3]; [[NSOperationQueue mainQueue] addOperation: inO];}-(void) test {NSLog (@ "test % s ----- % @", _ func __, [NSThread currentThread]) ;}# pragma mark # pragma mark-NSOperation Advanced Operations 2-(void) highLevelTest2 {/** NSOperation advanced operation scenario: improve user experience first. When a user operates, cancel all processes unrelated to the user's current operation, improve smoothness 1. add operation dependency 2. management Operation: Focus! Is the queue operation method 2.1 pause/resume cancel Operation 2.2 enable the appropriate number of threads! Generally, the Operation queue is set to a global variable (attribute) */NSBlockOperation * block1 = [NSBlockOperation blockOperationWithBlock: ^ {NSLog (@ "---------");}]; NSOperationQueue * queue = [[NSOperationQueue alloc] init]; [queue addOperationWithBlock: ^ {[self test];}]; [queue addOperation: block1]; // 1. when the pause operation starts to scroll, [queue setsuincluded: YES]; // 2. [queue setsuincluded: NO] at the end of the restore operation sliding; // 3. cancel all operations and receive a memory warning [queue cancelAllOp Erations]; // 3.1 supplement: cancel a single operation and call the cancel method [block1 cancel] for this NSOperation; // 4. set the maximum number of threads and enable the appropriate number of threads. [queue setMaxConcurrentOperationCount: 6] when instantiating the operation queue;/** when to choose GCD in case of concurrent programming, when to choose NSOperation 1. simply enable the thread/return to the main thread and select GCD: higher efficiency, simple 2. management operations required (considering user interaction !) Use NSOperation */} # pragma mark-NSOperation simple operation-(void) BaseTest {// 1. instantiate the operation object NSBlockOperation * blockOperation1 = [NSBlockOperation blockOperationWithBlock: ^ {NSLog (@ "blockOperation1 --------- % @", [NSThread currentThread]);}]; // append [blockOperation1 addExecutionBlock: ^ {NSLog (@ "addblockOperation1.1 ----- % @", [NSThread currentThread]);}]; [blockOperation1 addExecutionBlock: ^ {NS Log (@ "addblockOperation1.2 ----- % @", [NSThread currentThread]) ;}];/** after the number of tasks in NSBlockOperation is greater than 1, no matter whether you add an operation to the main thread or directly execute start in the main thread, the task execution sequence in NSBlockOperation is unknown, and the execution thread is not sure! During development, avoid appending tasks to NSBlockOperation! If the tasks are all executed in sub-threads, and the execution sequence does not need to be ensured! You can directly append the task */NSBlockOperation * blockOperation2 = [NSBlockOperation blockOperationWithBlock: ^ {NSLog (@ "blockOperation2 --------- % @", [NSThread currentThread]);}]; NSBlockOperation * blockOperation3 = [NSBlockOperation blockOperationWithBlock: ^ {NSLog (@ "blockOperation3 --------- % @", [NSThread currentThread]);}]; // Add the operation to a non-main queue column // NSOperationQueue * queue = [[NSOperationQueue alloc] init]; // [queue addOperation: blockOperation1]; // [queue addOperation: blockOperation2]; // [queue addOperation: blockOperation3]; // Add the operation to the main queue column [[NSOperationQueue mainQueue] addOperation: blockOperation1]; [[NSOperationQueue mainQueue] addOperation: blockOperation2]; [[NSOperationQueue mainQueue] addOperation: blockOperation3];}

 

 

3. NSOperation implements inter-thread Communication

1) use a proxy for message transmission

@ Interface ViewController () <MyOperationDelegate> @ property (weak, nonatomic) IBOutlet UIImageView * imageView; @ end @ implementation ViewController-(void) touchesBegan :( NSSet <UITouch *> *) touches withEvent :( UIEvent *) event {NSLog (@ "% s ----- % @", _ func __, [NSThread currentThread]); NSString * urlString = @ "http://h.hiphotos.baidu.com/image/pic/item/30adcbef76094b366b2389d7a4cc7cd98d109d53.jpg "; // 1. create the operation object MyOperation * myO = [[MyOperation alloc] init]; myO. delegate = self; // 3. tell myO which image is downloaded. urlString = urlString; NSOperationQueue * queue = [[NSOperationQueue alloc] init]; [queue setMaxConcurrentOperationCount: 6]; // 4. add the operation to the operation queue [queue addOperation: myO]; NSLog (@ "end") ;}# pragma mark # pragma mark-proxy method for implementing the operation-(void) downImage :( UIImage *) image {NSLog (@ "% s ------ % @", _ func __, [NSThread currentThread]); self. imageView. image = image ;}@ protocol MyOperationDelegate <NSObject>-(void) downImage :( UIImage *) image; @ end @ interface MyOperation: NSOperation @ property (nonatomic, copy) NSString * urlString; @ property (nonatomic, weak) id <MyOperationDelegate> delegate; @ end @ implementation MyOperation # pragma mark-Rewrite NSOperation's main method // after adding a custom operation to the operation queue or directly calling the start method of the operation, will automatically execute the content in the main method-(void) main {NSLog (@ "% s ------ % @", _ func __, [NSThread currentThread]); UIImage * image = [self downLoadImageSubThread]; // return to the main thread and execute the proxy method dispatch_async (dispatch_get_main_queue (), ^ {if ([self. delegate respondsToSelector: @ selector (downImage :)]) {[self. delegate downImage: image] ;}}) ;}# pragma mark # pragma mark-Method for downLoadImageSubThread {NSURL * url = [NSURL URLWithString: self. urlString]; NSData * data = [NSData dataWithContentsOfURL: url]; NSLog (@ "download completed"); return [UIImage imageWithData: data];} @ end

 

 

2) use notifications for message transmission

@ Interface ViewController () @ property (nonatomic, weak) IBOutlet UIImageView * imageView04; @ end @ implementation ViewController-(void) viewDidLoad {NSLog (@ "% s ----- % @", _ func __, [NSThread currentThread]); // register the notification observer // object: nil, nil can ensure that the observer receives any type of notification! [[Nsicationcenter center defacenter center] addObserver: self selector: @ selector (setUpImageWithNotify :) name: @ "FinishDownLoadImage" object: nil];}-(void) dealloc {// after the notification is used up, remove [[NSNotificationCenter defaultCenter] removeObserver: self];} // After receiving the notification, run noti: received notification-(void) setUpImageWithNotify :( NSNotification *) noti {NSLog (@ "% s ----- % @", _ func __, [NSThread currentThread]); // display the image self. imageView04.image = noti. object;}-(void) touchesBegan :( NSSet <UITouch *> *) touches withEvent :( UIEvent *) event {NSLog (@ "% s ----- % @", _ func __, [NSThread currentThread]); // 1. create an operation queue NSOperationQueue * queue = [[NSOperationQueue alloc] init]; [queue setMaxConcurrentOperationCount: 6]; // 2. tell the image MyOperation * myO = [[MyOperation alloc] init]; myO. urlString = @ "http://h.hiphotos.baidu.com/image/pic/item/72f082025aafa40f7c884d31af64034f79f0198b.jpg"; // 3. adding an operation to the operation queue automatically calls the main method [queue addOperation: myO]; NSLog (@ "end");} in the operation ");} /*************************************** * ********** // custom NSOperation class @ interface MyOperation: NSOperation @ property (nonatomic, copy) NSString * urlString; @ end // implement custom NSOperation class @ implementation MyOperation-(void) main {NSLog (@ "% s ----- % @", _ func __, [NSThread currentThread]); // download the image from the sub-thread and pass it to the main thread UIImage * image = [self downLoadImage: self. urlString]; // After the image is downloaded, use the notification to inform the Controller that the image download is complete and pass the downloaded image to the Controller. // send the notification dispatch_async (dispatch_get_main_queue () in the main thread (), ^ {[[nsnotifcenter center defacenter center] postNotificationName: @ "FinishDownLoadImage" object: image] ;};}- (UIImage *) downLoadImage :( NSString *) urlString {NSURL * url = [NSURL URLWithString: urlString]; NSData * data = [NSData dataWithContentsOfURL: url]; return [UIImage imageWithData: data];}

 

3) Use block for message transmission

@ Interface ViewController () @ property (weak, nonatomic) IBOutlet UIImageView * imageView; @ end @ implementation ViewController-(void) touchesBegan :( NSSet <UITouch *> *) touches withEvent :( UIEvent *) event {NSLog (@ "% s ---- % @" ,__ func __, [NSThread currentThread]); NSString * urlString = @ "http://h.hiphotos.baidu.com/image/pic/item/72f082025aafa40f7c884d31af64034f79f0198b.jpg "; // 2. create MyOperation * mo = [[MyOperation alloc] init]; mo. urlString = urlString; mo. view = self. view; [mo downLoadWebImageWithBlock: ^ (UIImage * image) {self. imageView. image = image;}]; [mo setCompletionBlock: ^ {NSLog (@ "image download completed") ;}]; NSLog (@ "end ");} /*************************************** * **************** // customize NSOperation class typedef void (^ downLoadBlock) (UIImage * image); @ interface MyOperation: NSOperation @ property (nonatomic, strong) UIView * view; @ property (nonatomic, copy) NSString * urlString; @ property (nonatomic, copy) downLoadBlock block;-(void) downLoadWebImageWithBlock :( downLoadBlock) blk; @ end // implement custom NSOperation class @ implementation MyOperation # pragma mark-implement the block method, you can directly press enter to call-(void) downLoadWebImageWithBlock :( downLoadBlock) blk {if (blk) {self. block = blk; dispatch_async (dispatch_get_global_queue (0, 0), ^ {UIImage * image = [self downLoadImage: self. urlString]; dispatch_async (dispatch_get_main_queue (), ^ {if (self. block) {self. block (image) ;}}) ;}}# pragma mark # pragma mark-Method for downLoadImage-(UIImage *) downLoadImage :( NSString *) strUrl {NSLog (@ "% s ---- % @" ,__ func __, [NSThread currentThread]); NSURL * url = [NSURL URLWithString: strUrl]; NSData * data = [NSData dataWithContentsOfURL: url]; NSLog (@ "download completed"); return [UIImage imageWithData: data];} @ end

 

 

Iv. Comparison with GCD

GCD:

Add a task (block) to the queue (Serial/concurrent/main queue column), and specify the function (synchronous/asynchronous) for task execution)
GCD is an API consisting of the underlying C Language
Concurrent Technology for multi-core processors launched in iOS 4.0
Tasks in a queue are composed of blocks. This is a lightweight data structure.
To stop a block already added to the queue, you need to write complicated code.
Dependencies between tasks need to be set through barriers or synchronization tasks
Only the queue priority can be set.
Advanced features:
Once
Delayed operation after
Scheduling Group

NSOperation:

Core Concept: add an operation (asynchronous) to a queue (Global concurrent Queue)
The OC framework is more object-oriented and is an encapsulation of GCD.
After Apple launched GCD in iOS 2.0, all underlying NSOperation layers were rewritten.
Operation, as an object, provides us with more options.
You can cancel the tasks that have been set to be executed at any time, except those that have been executed
Allows you to set operational dependencies across queues.
You can set the priority of each operation in the queue.
Advanced features:
Maximum number of concurrent operations (GCD is not good)
Continue/pause/cancel all
Cross-queue set operation dependency

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.