0

I've created a singleton class using this code:

static MyClass *sharedMyClass = nil;

+ (id)getInstance {
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    sharedMyClass = [[self alloc] init];
  });
  return sharedMyClass;
}

my concern is that the users of my class can call the alloc method an create other instantiations of the class. Therefore this would no longer be a singleton Do I need to override the alloc method? If so I suggest overriding it this way:

+ (id)alloc
{
  id instance = sharedMyClass;
  if (instance == nil) {
    instance = [super alloc];
  }
  return instance;
}
  • +(id)alloc { @synchronized([MyClass class]) { NSAssert(_sharedNavTheme == nil, @"Attempted to allocate a second instance of a singleton."); _sharedMyClass = [super alloc]; return _sharedMyClass; } return nil; } – Prajeet Shrestha Aug 27 '14 at 09:49

3 Answers3

1

Implement it this way?

+(id)alloc
{ @synchronized([MyClass class])
    {
        NSAssert(_sharedMyClass == nil, @"Attempted to allocate a second instance of a singleton.");
        _sharedMyClass = [super alloc];
        return _sharedMyClass;
    }
    return nil;
}
Prajeet Shrestha
  • 7,978
  • 3
  • 34
  • 63
0

Yes, you need to overwrite the alloc methode.

You can archive this by implementing

+ (instancetype)sharedInstance {
    static MyClass *sharedInstance = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[super allocWithZone:NULL] init];
    });

    return sharedInstance;
}

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

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

Apple provides a detailed description for this case which you can find here (non ARC description) https://developer.apple.com/legacy/library/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html#//apple_ref/doc/uid/TP40002974-CH4-SW32

charlyatwork
  • 1,187
  • 8
  • 13
0

You can forbid alloc at compile time:

+ (instancetype)new NS_UNAVAILABLE;
+ (instancetype)alloc NS_UNAVAILABLE;

Using super alloc in your own implementation:

+ (instancetype)getInstance {
  static id sharedMyClass
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    sharedMyClass = [[super alloc] init];
  });
  return sharedMyClass;
}

It doesn't protect you from some runtime code, but it's clear enough.

Cœur
  • 37,241
  • 25
  • 195
  • 267