iOS single-instance explanation

Source: Internet
Author: User

A singleton design pattern is often used in development to create only instance objects of a class for the entire life of a program, and the instance object will not be freed as long as the program is not killed. Let's look at the concepts, uses, and how to create a singleton to deepen our understanding.

Role

    • When you apply this pattern, the class of the Singleton object must guarantee that only one instance exists. Many times the entire system needs to have only one global object, which helps us coordinate the overall behavior of the system. For example, in app development we may use the user's information anywhere, then you can log in the user information in a file, the configuration data is read by a singleton object, and then the other objects in the service process through the Singleton object to obtain these configuration information. This approach simplifies configuration management in complex environments.

    • In some cases, a class may have only one instance. For example, if you write a class to play music, then you can only have one instance of that class to play the sound at any time. For example, a computer can be connected to several printers, but the printer on this computer can only have one, here you can use a singleton mode to avoid the simultaneous output of two print tasks to the printer, that is, throughout the printing process I have only one instance of the print program.

Create a single case

There are two ways to create a singleton, each of which describes

1, GCD way to create a single case

123456789101112131415161718192021222324 static id _instance;+ (instancetype)allocWithZone:(struct _NSZone *)zone{static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{_instance = [superallocWithZone:zone];});return_instance;}+ (instancetype)sharedInstance{static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{_instance = [[self alloc] init];});return_instance;}- (id)copyWithZone:(NSZone *)zone{return_instance;}- (id)mutableCopyWithZone:(NSZone *)zone {return_instance;}

2, mutual exclusion lock mode

1234567891011121314151617181920212223 static id _instance;+ (instancetype)allocWithZone:(struct _NSZone *)zone{@synchronized(self) {if(_instance == nil) {_instance = [superallocWithZone:zone];}}return_instance;}+ (instancetype)sharedInstance{@synchronized(self) {if(_instance == nil) {_instance = [[self alloc] init];}}return_instance;}- (id)copyWithZone:(NSZone *)zone{return_instance;}

The above two ways can create a singleton, and ensure that the user either through the Shareinstance method, or the Alloc, copy method to get the same instance.

The key point of the above code is how to guarantee the creation of the singleton or the same one in multithreaded situations.

Let's take a look at the GCD case, if you don't use dispatch_once and sync locks to create a single-session problem, remove the two and create a singleton code as follows

123456 + (instancetype)sharedInstance{if(_instance == nil) {_instance = [[self alloc] init];}}

Assuming there are two threads at this time: Thread 1 and Thread 2, all calling the Shareinstance method to create the singleton, then thread 1 runs to if (_instance = = nil) out of the discovery _instance = nil, then initializes a _instance, Assuming that thread 2 is also running at the discretion of the IF, thread 1 has not yet created the completion instance _instance, so at this point _instance = nil or set, then thread 2 will create a _instace.

At this point, two instance objects are created, causing the problem.

Workaround 1, use Dispatch_once

Dispatch_once guarantee that the program will run only once, then assume that thread 1 executes the Shareinstance method first, create an instance object, thread 2 will no longer execute dispatch_once code. This ensures that only one instance object is created.

Workaround 2, use mutex lock

Assuming thread 1 is executing the Shareinstance method at this point, create a singleton code inside the synchronize brace, as follows:

123 if(_instance == nil) {_instance = [[self alloc] init];}

will be treated as a task to be added a lock. At this point, assume that thread 2 also wants to execute the Shareinstance method to create a singleton, but see the thread 1 plus the mutex, will go into sleep mode. Wait until thread 1 is completed before it wakes up, then executes the code shown above to create the singleton, but at this point _instance!=nil, so no new instance objects are created. This ensures that only one instance object is created.

But mutexes can affect performance, so it's best to create a singleton using the GCD method.

Macro Create a single case

If we need to create more than one singleton in a program, it is tedious to write the above code once in each class.

We can use macros to encapsulate the creation of a singleton, so that any class needs to create a singleton, just one line of code to get it done.

Implementation code

1234567891011121314151617181920212223242526272829303132 Singleton.h文件==================================#define SingletonH(name) + (instancetype)shared##name;#define SingletonM(name) \static id _instance; \\+ (instancetype)allocWithZone:(struct _NSZone *)zone \{ \static dispatch_once_t onceToken; \dispatch_once(&onceToken, ^{ \_instance = [superallocWithZone:zone]; \}); \return_instance; \} \\+ (instancetype)shared##name \{ \static dispatch_once_t onceToken; \dispatch_once(&onceToken, ^{ \_instance = [[self alloc] init]; \}); \return_instance; \} \\- (id)copyWithZone:(NSZone *)zone \{ \return_instance; \}\\- (id)mutableCopyWithZone:(NSZone *)zone { \return_instance; \}

How to Invoke

Suppose we want to use it in class Viewcontroller, call the following method:

123456789101112131415161718 viewcontroller.h文件===========================#import#import "Singleton.h"@interface ViewController : UIViewControllerSingletonH(viewController)@endviewcontroller.m文件===========================@interface ViewController ()@end@implementation ViewControllerSingletonM(ViewController)- (void)viewDidLoad {[superviewDidLoad];NSLog(@"%@ %@ %@ %@", [ViewController sharedViewController],[ViewController sharedViewController], [[ViewController alloc] init],[[ViewController alloc] init]);}@end

Output results

iOS single-instance explanation

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.