Singleton Implementation. Blocking the alloc and init methods for external usage

1k Views Asked by At

I have a Class that I wish to implement as Singleton.

I wish that the only way an Instance of this class may be created / accessed is via:

+(MYClass*)sharedInstance 

method. alloc and init are called within the method implementation (of course).

Is there a way to block the usage of alloc and init, or to make them 'empty', if there's an attempt to create an instance of that class NOT via the sharedInstance method (but through alloc + init directly)?

2

There are 2 best solutions below

5
On

If you are using arc, add compiler flag -fno-objc-arc to the file.

"alloc + init" will call sharedManager method.

static MyGizmoClass *sharedGizmoManager = nil;

+ (MyGizmoClass*)sharedManager
{
    if (sharedGizmoManager == nil) {
        sharedGizmoManager = [[super allocWithZone:NULL] init];
    }
    return sharedGizmoManager;
}

+ (id)allocWithZone:(NSZone *)zone
{
    return [[self sharedManager] retain];
}

- (id)copyWithZone:(NSZone *)zone
{
    return self;
}

- (id)retain
{
    return self;
}

- (NSUInteger)retainCount
{
    return NSUIntegerMax;  //denotes an object that cannot be released
}

- (void)release
{
    //do nothing
}

- (id)autorelease
{
    return self;
}
3
On

Putting this code in your header file should produce a compile time error if init is called outside the implementation:

- (id)init __attribute__((unavailable("cannot use init for this class, use +(MYClass*)sharedInstance instead")));

I found this technique here.

Update:

You won't be able to write [[MYClass alloc] init] in your .m file but you can use the following:

+ (MYClass *)sharedInstance {
    static MYClass *sharedInstance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [self new];
    });
    return sharedInstance;
}