GCD notes

Recommended for you: Get network issues from WhatsUp Gold. Not end users.

One, what is GCD?

  Grand Central Dispatch (GCD)Is a methodology for solving multi core programming Apple development. The method was first introduced in Mac OS X 10.6 snow leopard, and then was introduced to iOS4.0. GCD is an alternative to such as NSThread, NSOperationQueue, NSInvocationOperation technology is very efficient and powerful technique.

Two, when using multiple threads

  My personal understanding, in the actual development we often put those time-consuming and has nothing to do with UI's operation in the non main thread to execute, avoid the time-consuming operation blocking main thread to operate much card interface. For example: load the network data, local storage, read, update the data in these cases should use multiple threads.

Three, not GCD

  In the absence of GCD, when dealing with multi thread you may be using a (NSThread), (NSOperationQueue and NSInvocationOperation binding), or several convenient methods for the use of iOS:

- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0);

- (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg NS_AVAILABLE(10_5, 2_0);

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;

These methods have a common disadvantage is the code is relatively dispersed, reduce the readability of the program

For example, the code below: (copyright for Tang Qiao)

static NSOperationQueue * queue;

- (IBAction)someClick:(id)sender {
    self.indicator.hidden = NO;
    [self.indicator startAnimating];
    queue = [[NSOperationQueue alloc] init];
    NSInvocationOperation * op = [[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil] autorelease];
    [queue addOperation:op];
}

- (void)download {
    NSURL * url = [NSURL URLWithString:@"http://www.youdao.com"];
    NSError * error;
    NSString * data = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
    if (data != nil) {
        [self performSelectorOnMainThread:@selector(download_completed:) withObject:data waitUntilDone:NO];
    } else {
        NSLog(@"error when download:%@", error);
        [queue release];
    }
}

- (void) download_completed:(NSString *) data {
    NSLog(@"call back");
    [self.indicator stopAnimating];
    self.indicator.hidden = YES;
    self.content.text = data;
    [queue release];
}

Four, with GCD

Because GCD uses block syntax, so we can put the code block operation on the block to execute (strongly recommended to understand a number of block related knowledge before reading this article), another advantage is that the GCD API all C language and apple is strongly recommended to use, so people feel in the processing efficiency several other methods should be relatively higher.

If you use GCD, the above 3 methods can be put together, as shown below:

// The original code block
self.indicator.hidden = NO;
[self.indicator startAnimating];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // The original code block two
    NSURL * url = [NSURL URLWithString:@"http://www.youdao.com"];
    NSError * error;
    NSString * data = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
    if (data != nil) {
        // The original code block three
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.indicator stopAnimating];
            self.indicator.hidden = YES;
            self.content.text = data;
        });
    } else {
        NSLog(@"error when download:%@", error);
    }
});

Five, the dispatch method provides system

At first glance, the syntax of GCD seems very complicated, is actually very simple, apple for the convenience of our use of GCD, provides the background, the main thread to execute, execute after a series of methods are as follows:

 //  Background execution: 
 dispatch_async(dispatch_get_global_queue(0, 0), ^{
      // something
 });
 // The main thread execution: 
 dispatch_async(dispatch_get_main_queue(), ^{
      // something
 });
 // One-time implementation: 
 static dispatch_once_t onceToken;
 dispatch_once(&onceToken, ^{
     // code to be executed once
 });
 // A delay of 2 seconds to perform: 
 double delayInSeconds = 2.0;
 dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
 dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
     // code to be executed on the main queue after delay
 });

Dispatch_queue_t can also define their own, such as to a custom queue, can use the dispatch_queue_create method, examples are as follows:

dispatch_queue_t urls_queue = dispatch_queue_create("blog.devtang.com", NULL);
dispatch_async(urls_queue, ^{
     // your code
});
dispatch_release(urls_queue);

Two threads in parallel

Parallel queue is created not allowed, there are parallel queue three different priority system. Parallel queue is still in accordance with the task of adding sequential priming task, but, after a task without waiting for a previous task completed, but to start the first task, start the next task immediately. As the same time allowed to run at the same time the number of task system. The operation to provide for them in parallel queue independent thread in the queue, parallel running at the same time the number of tasks, we must maintain the number of threads.


 UInt32 loopCount = 1000;
UInt32 loopCountFirst = 10000000;
void (^taskFirst)(void) = ^{
     NSLog(@"The taskFirst task started the implementation of \r\n"); 
     //The operation time of taskFirst
     for (UInt32 i = 0; i <loopCountFirst; i++) {          
     }
     NSLog(@"TaskFirst over \r\n");
};    
    void (^taskSecond)(void) = ^{
      NSLog(@"The taskSecond task started the implementation of \r\n");
       for (UInt32 i = 0; i <loopCount; i ++) {             
       }
      NSLog(@"TaskSecond over \r\n");
 };
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, taskFirst);
NSLog(@"Taskfirst has joined the queue \r\n");
dispatch_async(concurrentQueue, taskSecond);
NSLog(@"Tasksecond has joined the queue \r\n");

In addition, GCD also has some advanced usage, for example let the backstage 2 threads are executed in parallel, then the 2 threads are finished, and summary execution results. This can be used dispatch_group, dispatch_group_async and dispatch_group_notify to achieve, examples are as follows:

 dispatch_group_t group = dispatch_group_create();
 dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
      // Parallel thread execution
 });
 dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
      // Two parallel thread execution
 });
 dispatch_group_notify(group, dispatch_get_global_queue(0,0), ^{
      // Summary of results
 });

Six, summary

The interaction of GCD greatly facilitates iOS developers use the multi thread to complete the data with UI, and full use of multi-core processor function today, not only improves the efficiency and is convenient for use.

Thank you very much Qiao Tang a GCD to use the article, in this article some of the content I felt unable to write good than the Tang Qiao excerpts here, please understanding!

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Posted by Natasha at December 05, 2013 - 6:55 AM