I would like to take the GCD approach of using shared instances to the next step so I created the following code:
@implementation MyClass
static id sharedIn
The general opinion is that trying to protect your singleton against that kind of bug is pointless. Whoever calls [[LUIMain alloc] init]
and creates a singleton gets what they deserved.
And the code that you wrote isn't thread safe anyway. If I call [[LUIMain alloc] init]
while someone else calls sharedInstance, sharedInstance will return a different object than on the next call. (@synchronized (self)
in the init method is pointless, because a second caller will have a different self).
I would like to suggest new ways of solving your problem.
You can use NS_UNAVAILABLE
in the header file just like this:
//Header file
@interface MyClass : NSObject
+ (instancetype)sharedInstance
- (instancetype)init NS_UNAVAILABLE;
//...
@end
In this case init
function will not be available from outside, will not be suggested for autocompletion, and you'll be able to normally use the init
method inside implementation file.
As you are making a singleton class I would suggest you to make new
method unavailable too by adding this line to the header file:
+ (instancetype)new NS_UNAVAILABLE;
There is also an old way of making methods unavailable (which can be used in header too):
- (instancetype) init __attribute__((unavailable("Use 'sharedInstance' instead of 'init' as this class is singleton.")));
This can be used if you want to prompt some message about unavailability.
Instead of transparently redirecting calls to init
to the singleton implementation which can cause very confusing behaviour for the users of your SDK, I suggest not allowing to call init at all:
+ (instancetype)sharedInstance {
static dispatch_once_t once;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] initPrivate];
});
return sharedInstance;
}
- (instancetype)init {
@throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"..." userInfo:nil];
}
- (instancetype)initPrivate {
if (self = [super init]) {
...
}
return self;
}