Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Safe way to create singleton with init method in Objective-C

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 sharedInstance;

#pragma mark Initialization

+ (instancetype)sharedInstance {
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

- (instancetype)init {
    if (sharedInstance) {
        return sharedInstance;
    }
    @synchronized(self) {
        self = [super init];
        if (self) {
            sharedInstance = self;
        }
        return self;
    }
}

@end

I assume the sharedInstance method seems to be ok but I am unsure about the init method. The reason for creating this is that I don't want people using my SDK, to use the init method, and if they do ... make it bullet proof.

like image 208
Ondrej Rafaj Avatar asked Apr 20 '15 12:04

Ondrej Rafaj


People also ask

Can we de init a singleton object?

If you have a regular object that you can't deinitialize it's a memory problem. Singletons are no different, except that you have to write a function to do it. Singletons have to be completely self managed. This means from init to deinit.

How do you call a singleton class in Objective C?

Then you can reference the singleton from anywhere by calling the following function: MyManager *sharedManager = [MyManager sharedManager]; I've used this extensively throughout my code for things such as creating a singleton to handle CoreLocation or CoreData functions.

How do you call an init method in Objective C?

Whenever an object is "created" by default it is supposed to be done with myObject=[[MyObjectClass alloc]init] or the equivalent shortcut myObject=[MyObjectClass new] . That is where your init method is called.

Why use singleton in Swift?

The main advantage of the singleton pattern is its ease of access. Wherever you need the shared instance, you can access it without modifying your code further. It's also possible to enforce a single instance if you make the Facade class's initializer private.


1 Answers

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.

like image 159
Just Shadow Avatar answered Oct 17 '22 13:10

Just Shadow