Your observation is correct, many of the "singleton" patterns that you see in Objective-C are not singletones at all, but rather a "shared instance" model where other instances can be created.
In the old days of MRC, Apple used a sample code showing how to implement a real singleton.
The code you have is the recommended template for ARC and thread safe singleton, you just need to put it in the init method:
- (instancetype) init { static MyClass *initedObject; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ initedObject = [super init]; }); return initedObject; }
This code ensures that there is only one instance of MyClass , regardless of the number of calls to [MyClass new] or [[MyClass alloc] init] .
This is all you need to do, but you can move on. First, if you want the class method to return a singleton, it is simple:
+ (instancetype) singletonInstance { return [self new]; }
This method ends with an init call that returns singleton, creating it if necessary.
If MyClass implements NSCopying , you also need to implement copyWithZone: - a method that calls copy . Since you have a singleton, it's really simple:
- (instancetype) copyWithZone:(NSZone *)zone { return self; }
Finally, in Objective-C, the operations of allocating an instance of a new object and initializing it are different. The above diagram ensures that only one instance of MyClass initialized and used, however, for each call to new or alloc , another instance is allocated, which is then discarded by init and cleared by ARC. This is somewhat wasteful!
This is easily solved by implementing allocWithZone: (e.g. copy above, this alloc method actually ends the call), following the same pattern as for init :
+ (instancetype) allocWithZone:(NSZone *)zone { static MyClass *allocatedObject; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ allocatedObject = [super allocWithZone:zone]; }); return allocatedObject; }
The first time an instance is created, then allocWithZone: will allocWithZone: it, and then init initialize it, all subsequent calls will return an existing object. No discarded unnecessary distributions.
That it is a true singleton, and no more complicated than the faux-singletons that are so common.
NTN