-2

As we know that a singleton object can be instantiated only once and we use singletons in objective C to have a global access to shared resources. We also know that singletons are instantiated using the following method.

    + (instancetype)sharedManager
{
    static PhotoManager *sharedPhotoManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedPhotoManager = [[[self class] alloc] init];
        sharedPhotoManager->_photosArray = [NSMutableArray array];
    });
    return sharedPhotoManager;
}

But I can also do this -

PhotoManager *sharedManager = [[PhotoManager alloc] init];

Now this way I can also create another instance of the same singleton class then how come the class is singleton if it is having two instances.

Please clarify.

Aisha
  • 1,559
  • 5
  • 20
  • 37

4 Answers4

2

You can forbid calls of init with such trick: add - (instancetype)init NS_UNAVAILABLE; definition to your singleton interface.

Instead of [[PhotoManager alloc] init]; use [[[self class] alloc] init];

PhotoManager *sharedManager = [[PhotoManager alloc] init]; won't compile.

There is my example:

@interface SomeSingleton : NSObject

+ (instancetype)sharedInstance;
- (instancetype)init NS_UNAVAILABLE;

@end

@implementation SomeSingleton

+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    static SomeSingleton *instance;
    dispatch_once(&onceToken, ^{
        instance = [[[self class] alloc] init];
    });

    return instance;
}

- (instancetype)init {
    self = [super init];

    return self;
}

@end

As result SomeSingleton *s1 = [SomeSingleton sharedInstance]; works, but SomeSingleton *s2 = [[SomeSingleton alloc] init]; leads to the compile error.

Vitaly S.
  • 2,389
  • 26
  • 40
0

You have singleton behaviour for object only when you use sharedManager: class method. All other ways you instantiate object are not guaranteed to produce singleton object.

John Tracid
  • 3,836
  • 3
  • 22
  • 33
0

Objective-C allows you to do lots of things that may not be intended. Like calling a private method if you know the method name.

If you are obsessed to make sure your class is only used as singleton, maybe something like this would be of use:

static PhotoManager *sharedPhotoManager = nil;

+ (instancetype)sharedManager
{
    if (!sharedPhotoManager) {
        sharedPhotoManager = [[PhotoManager alloc] init];
    }
    return sharedPhotoManager;
}

- (instancetype)init {
    if (sharedPhotoManager) {
        // init method is allowed to return different object
        return sharedPhotoManager;
    }
    self = [super init];
    if (self) {

    }
    return self;
}
agilityvision
  • 7,901
  • 2
  • 29
  • 28
-1

When you write

PhotoManager *sharedManager = [[PhotoManager alloc] init];

you are not getting your sharedInstance, you are creating a new one. The way you should use it is

[PhotoManager sharedInstance];

instead of

PhotoManager *sharedManager = [[PhotoManager alloc] init];

When you create a singleton class you has never use alloc init, you always should use sharedInstance method to keep the same instance in your app

By the way... as T_77 suggest you, you should use dispatch_once instead of your implementation to create an instance.

 + (instancetype)sharedInstance
 {
     static dispatch_once_t once;
     static id sharedInstance;
     dispatch_once(&once, ^{
         sharedInstance = [[self alloc] init];
     });
     return sharedInstance;
 }
Community
  • 1
  • 1
Fran Martin
  • 2,369
  • 22
  • 19