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
static id _instance;   +  (Instancetype) Allocwithzone: (struct _NSZone * ) zone  {       static dispatch_once_t oncetoken;        dispatch_once (&onceToken, ^{            _instance = [super allocWithZone: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
static id _instance;+  (Instancetype) Allocwithzone: (struct _nszone *) zone{      @synchronized (self)  {        if  (_instance  == nil)  {            _instance =  [super allocWithZone: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

+ (Instancetype) sharedinstance {if (_instance = = nil) {_instance = [[Self alloc] init]; }}

Assuming there are two threads at this point: Thread 1 and Thread 2, all calling the Shareinstance method to create the singleton, then thread 1 runs to the if (_instance == nil) discovery _instance = nil, then initializes a _instance, assuming that thread 2 is also running to the judgment of the if at this point. , thread 1 has not yet created the completion instance _instance, so _instance = nil is still established, 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:

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
Singleton.h file ================================== #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 = [super allocWithZone: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:

Viewcontroller.h file =========================== #import #import "Singleton.h" @interface Viewcontroller: Uiviewcontrollersingletonh (Viewcontroller) @endviewcontroller. m file =========================== @interface Viewcontroller () @end @implementation viewcontrollersingletonm (viewcontroller)-(void) Viewdidload {[Super    Viewdidload]; NSLog (@ "%@%@%@%@", [Viewcontroller Sharedviewcontroller],[viewcontroller Sharedviewcontroller], [[Viewcontroller Alloc] Init],[[viewcontroller alloc] init]);} @end
Output results

You can see that the memory address of four objects is exactly the same, indicating that the same object

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.