“Writing High Quality OC Code” has been successfully completed chapter one, two, three, four, five, six, eight! Attach a link: Objective-c code for iOS (1) — Objective C code for iOS (2) — Objective C code for iOS (3) — Interface and API design Objective-c code (5) — Memory management mechanism (6) — Block column iOS Writing high quality Objective-C code for iOS (GCD


The topic of this article is the “Grand Central Development GCD” in iOS.

First, let’s briefly introduce today’s leading role: THE COMMUNIST Party of China.

  • The GCD (Grand Central Dispatch) : a block-related technology that provides abstract management of threads (based on dispatch queues)dispatch queue). The GCD will be efficient and timely based on system resources“Create Thread”, “reuse thread”, “Destroy Thread”.

First, distribute queue more, use synchronization lock less

Q: How do you use locks to provide synchronization in iOS development? (Frequently asked questions in previous interviews…)

A: Before the advent of COMMUNIST CD, there were two ways:

  • Synchronized block:@synchronized(self) {... }
- (void)synchronizedMethod { @synchronized (self) { // Safe area... }}Copy the code
  • NSLock:[_lock lock]; & [_lock unlock];
_lock = [[NSLock alloc] init];

- (void)synchronizedMethod {
    
    [_lock lock];    
    // Safe area..    
    [_lock unlock];
}
Copy the code

However, these two methods are inefficient. If there are many attributes, the synchronization block of each attribute will wait for the other synchronization blocks to complete.

With the advent of GCD, THE combination of GCD and Block makes development much simpler and more efficient.

Q: How can I keep the thread safe when reading and writing attributes? A: Use the barrier block when writing properties. The Barrier block is executed only after all current concurrent blocks have been executed, and then processing continues.

  • Here’s the idea:

  • The code is as follows:
_syncQueue = dispatch_queue_create("syncQueue", DISPATCH_QUEUE_CONCURRENT); / /! Read string - (NSString *)someString {__block NSString *localSomeString; dispatch_sync(_syncQueue, ^{ localSomeString = _someString; }); return localSomeString; } - (void)setSomeString:(NSString *)someString { dispatch_barrier_async(_syncQueue, ^{ _someString = someString; }); }Copy the code

Two, use GCD more and use performSelector less

The performSelector family of methods has two disadvantages:

  1. performSelectorA series of methods can cause memory leaks: In an ARC environment, the compiler does not know what selector will be called, whether it has a return value, and what the return value will be, so ARC cannot determine whether the return value can be freed, so ARC takes a more cautious approach: just addretain, don’t addrelease. Therefore, memory leaks can occur when there are return values or parameters.
  2. performSelectorThe return value of a series of methods can only be a void or OC object type.
  3. performSelectorA series method can take a maximum of two arguments.

So you can use GCD instead of the performSelector family of methods:

Dispatch_after (dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{//do something..
});
Copy the code

Master the use time of GCD and operation queue

GCD performance is great, but when it comes to performing background tasks, GCD is not always the best choice. In iOS development, there is also a technique called NSOperationQueue. GCD is an API based on THE C language with high performance. NSOperationQueue is a GCD-based abstraction.

Advantages of using NSOperation and NSOperationQueue:

  • Support for canceling an NSOperation: Before running a task, you can call the Cancel method on the NSOperation object to indicate that the task does not need to be executed. However, tasks that have been started cannot be cancelled. Before iOS 8, there was no way to cancel the GCD queue, and GCD was “Fire and Forget”. After iOS 8, dispatch_cancel and dispatch_block_cancel are supported.

  • NSOperation supports multi-task operations. For example, tasks A, B, and C must be executed after task D is complete.

  • KVO can be used to monitor the properties of NSOperation objects. For example, isCancelled property can be used to determine whether the task has been cancelled, and isFinished property can be used to determine whether the task has been completed.

  • You can specify the priority of NSOperationQueue: The priority of an operation indicates the priority relationship between this operation and other operations in the queue. The NSOperationQueue with a higher priority is executed first, and the NSOperationQueue with a lower priority is executed later. GCD queues also have priority, but not for the whole queue;

  • Reuse NSOperation objects: In development, you can subclass NSOperation or create your own NSOperation object to hold information. You can define methods in the class so that code can use them more than once.

4. Perform tasks according to the status of system resources through Dispatch Group mechanism

A Dispatch group is a GCD feature that allows you to group tasks into groups and then wait for a notification when the group of tasks is complete so the developer can get the results and move on. In addition, when multiple tasks are executed simultaneously on a concurrent queue through the Dispatch Group, the GCD will help schedule these concurrent tasks based on the system resource status.

Use dispatch_once to execute thread-safe code that only needs to be run once

For example, we can use dispatch_once if we write a singleton:

+ (instancetype)sharedInstance {
    
    static Class *manager = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[Class alloc] init];
    });

    return manager;
}
Copy the code

Do not use dispatch_get_CURRENT_queue

The reasons are as follows:

  • dispatch_get_current_queueFunctions often behave differently from what developers expect; this function is deprecated and should only be used for debugging.
  • Due to theGCDIt is organized hierarchically, so there is no single queue object to describe the concept of “current queue”.
  • dispatch_get_current_queueThe queue-specific data () function is used to resolve deadlocks caused by code that cannot be reentrant and can then be used to resolve the problem.