1

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.

Ashwani
  • 378
  • 1
  • 3
  • 13
  • 4
    http://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 Answers4

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