Correct format of Objective-c Singleton Mode
The Singleton mode may be one of the most common models in iOS development, but it is relatively difficult to write a correct Singleton mode due to the language characteristics of oc, here I will talk about the design ideas of the single sample mode in iOS. For more information about the singleton mode, see this article.
A Singleton, as its name implies, can only have one class instance. In java, C ++, constructor can be privatized to avoid repeated object creation, however, objective-c cannot do this. We need other mechanisms to do this. In general, we may write the singleton mode as follows:
#import
@interface Singleton : NSObject+(instancetype) shareInstance ;@end#import "Singleton.h"@implementation Singletonstatic Singleton* _instance = nil;+(instancetype) shareInstance{ static dispatch_once_t onceToken ; dispatch_once(&onceToken, ^{ _instance = [[self alloc] init] ; }) ; return _instance ;}@end
Specific use:
#import
#import "Singleton.h"int main(int argc, const char * argv[]) { @autoreleasepool { Singleton* obj1 = [Singleton shareInstance] ; NSLog(@"obj1 = %@.", obj1) ; Singleton* obj2 = [Singleton shareInstance] ; NSLog(@"obj2 = %@.", obj2) ; // Singleton* obj3 = [[Singleton alloc] init] ; NSLog(@"obj3 = %@.", obj3) ; } return 0;}
Output result:
2014-12-15 16:06:28.344 ObjcSingleton[8847:303] obj1 =
.2014-12-15 16:06:28.346 ObjcSingleton[8847:303] obj2 =
.2014-12-15 16:06:28.346 ObjcSingleton[8847:303] obj3 =
.
We can see that the obtained objects are the same when we call the invoke instance method, but the obtained objects are different when we construct objects through alloc and init.
Then the problem arises. It is obviously impossible for us to obtain different objects through different channels. We must ensure the uniqueness of the object, so we need to block the path through which users construct objects through alloc, init, and copy.
We know that the steps for creating an object are divided into two steps: applying for memory (alloc) and initializing (init). We need to ensure the uniqueness of the object, so we need to intercept it at the first step. When we call the alloc method, oc will call the allocWithZone method internally to apply for memory. We will override this method and then call the reset instance method in this method to return the singleton object, in this way, we can achieve our goal. The same principle applies to copying objects. Override the copyWithZone method and call the instance method in this method to return the singleton object. Check the Code:
#import "Singleton.h"@implementation Singletonstatic Singleton* _instance = nil;+(instancetype) shareInstance{ static dispatch_once_t onceToken ; dispatch_once(&onceToken, ^{ _instance = [[super allocWithZone:NULL] init] ; }) ; return _instance ;}+(id) allocWithZone:(struct _NSZone *)zone{ return [Singleton shareInstance] ;}-(id) copyWithZone:(struct _NSZone *)zone{ return [Singleton shareInstance] ;}@end
Let's see how it works:
main : #import
#import "Singleton.h"int main(int argc, const char * argv[]) { @autoreleasepool { Singleton* obj1 = [Singleton shareInstance] ; NSLog(@"obj1 = %@.", obj1) ; Singleton* obj2 = [Singleton shareInstance] ; NSLog(@"obj2 = %@.", obj2) ; // Singleton* obj3 = [[Singleton alloc] init] ; NSLog(@"obj3 = %@.", obj3) ; Singleton* obj4 = [[Singleton alloc] init] ; NSLog(@"obj4 = %@.", [obj4 copy]) ; } return 0;}
Output result:
2014-12-15 16:11:24.734 ObjcSingleton[8979:303] obj1 =
.2014-12-15 16:11:24.735 ObjcSingleton[8979:303] obj2 =
.2014-12-15 16:11:24.736 ObjcSingleton[8979:303] obj3 =
.2014-12-15 16:11:24.736 ObjcSingleton[8979:303] obj4 =
.
We can see that the obtained objects are the same.
This is the way of thinking. If there is more rigorous writing, please leave a message. Thank you ~