init method is declared in NSObject class hence, the client code can create a new instance of my singleton class, is there any way to achieve the real singleton such that client cannot create a new instance.
Asked
Active
Viewed 172 times
1
-
4http://stackoverflow.com/questions/7274360/how-objective-c-singleton-should-implement-init-method maybe duplicate question – brianLikeApple Oct 19 '12 at 13:06
-
You should look at [Peter Hosey's blog post](http://boredzo.org/blog/archives/2009-06-17/doing-it-wrong) on this topic. His implementation is a "true" singleton. – jscs Oct 19 '12 at 18:58
4 Answers
1
Just do this:
static SingletonClass *singleton;
+ (SingletonClass *)sharedInstance
{
@synchronized(self) { //For thread safety
if (singleton == nil) {
[[self alloc] init];
}
return singleton;
}
}
-(id)init
{
if (singleton) { //This way init will always return the same instance
return singleton;
}
self = [super init];
if (self) {
singleton = self;
}
return singleton;
}

Jack Freeman
- 1,414
- 11
- 18
-
You're going to leak an instance if a client does `[[SingletonClass alloc] init]`. You need to throw away the `self` instance that's passed in to `init` before you return `singleton`, or override `allocWithZone:` to return the shared instance, so that it's the one which is passed in to `init`. – jscs Oct 19 '12 at 18:54
-
Are you sure this will leak with arc? I was under the impression the autorelease pool will ditch it. – Jack Freeman Oct 19 '12 at 20:33
-
If `self` ever goes into an autorelease pool, then ARC needs some serious work. – jscs Oct 20 '12 at 07:27
-
I just made a quick sample project and it does in fact get released. So you are incorrect, ARC does take care of it, there is no leak here. – Jack Freeman Oct 20 '12 at 17:24
-
That is interesting. Would you throw your test code on pastebin or somewhere? – jscs Oct 20 '12 at 18:48
-
Here you go. It's just what I have above and then a simple for loop that tries to create 1000 instances http://pastebin.com/dRDHwghc – Jack Freeman Oct 20 '12 at 23:34
-
Okay, ARC does indeed know how to do the right thing there. _Very_ interesting. (Note that there is no autorelease pool involved.) After puzzling over this, I found the reason: ["Consumed parameters"](http://clang.llvm.org/docs/AutomaticReferenceCounting.html#objects.operands.consumed), specifically "The implicit self parameter of a method may be marked as consumed by adding __attribute__((ns_consumes_self)) to the method declaration. Methods in the init family are treated as if they were implicitly marked with this attribute." – jscs Oct 21 '12 at 18:09
0
This is a proper way to do a singleton in objective c
+ (id)sharedManager
{
static dispatch_once_t onceQueue;
static SingletonObjectClass *singleton = nil;
dispatch_once(&onceQueue, ^{
singleton = [[self alloc] init];
});
return singleton;
}
- (id)init {
self = [super init];
if (self) {
//.....
}
return self;
}

rule
- 5,657
- 1
- 16
- 21
-
By itself, this doesn't restrict creation to only one instance. A client can still `alloc` another. – jscs Oct 19 '12 at 18:52
-1
init method is for initialization of instance variables. on its own will not create the object. Alloc, copy methods needs to be overridden to achieve a real single ton.
Hope this should clarify.
+ (id)alloc {
NSLog(@"%@: use +sharedInstance instead of +alloc", [[self class] name]);
return nil;
}
+ (id)new {
return [self alloc];
}
+ (SingletonClass *)sharedInstance {
static SingletonClass *myInstance = nil;
if (!myInstance)
{
myInstance = [[super alloc] init];
}
return myInstance;
}

nkongara
- 1,233
- 8
- 14
-
I still cannot hide the alloc method from the client code as it is declared in NSObject. – Ashwani Oct 19 '12 at 13:14
-1
You can return a static object of the class each time, making it a singleton.
@implementation Singleton
@synthesize testVar;
+ (Singleton*) sharedObject {
static Singleton * myInstance = nil;
if (myInstance == nil) {
myInstance = [[[self class] alloc] init];
testVar = 5;
// Set default values if needed
return myInstance;
}
To access object and its members:
[[Singleton sharedObject] testVar]

Martol1ni
- 4,684
- 2
- 29
- 39