0

Im trying to get an updated version of the Singleton Design Pattern which is thread safe. Here is one version that I know. However, I cannot make it work in iOS6

Here is what Im trying to do:

Here is my Class method

 +(id)getSingleton
 {
    static dispatch_once_t pred;
    static EntryContainerSingleton *entriesSingleton = nil;
    dispatch_once(&pred, ^{
        entriesSingleton = [[super alloc] init];

        });

    return entriesSingleton;   
   }

 +(id)alloc
 {
  @synchronized([EntryContainerSingleton class])
  {
      NSLog(@"inside alloc of EntryContainerSingleton");
   ERROR >>>>>  NSAssert(entriesSingleton == nil, @"Attempted to allocate a second instance of a singleton.");
   ERROR >>>>>   entriesSingleton = [super alloc];
   ERROR >>>>>   return entriesSingleton;
   }
  return nil;
  }

  -(id)init
  {
     self = [super init];
     ......Some custom INitialization
     return self;
 }

This code throws an error as marked above. The error message says Use of undeclared identifier. In addition the link above recommends the use of

  [[allocWithZone:nil] init] 

When I use it like this it complains

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

After hours of trying to make it work. It would be great if someone could point out how to do this right. Ive spent much time googling and haven't found a complete implementation example.

Thanks

Community
  • 1
  • 1
banditKing
  • 9,405
  • 28
  • 100
  • 157
  • take a look at **[this answer](http://stackoverflow.com/questions/14646576/singleton-in-objective-c-compatible-with-arc-and-thread-safe/14646980#14646980)**... it is working well in iOS5 and iOS6 as well. – holex Feb 03 '13 at 01:37
  • Note that the accepted answer to that question is somewhat reasonable in the case that you absolutely can never have two instances, and it would be an error even to try. That is a very rare case in ObjC. In almost all cases, the code in the question (not the answer) is correct. – Rob Napier Feb 03 '13 at 01:47
  • @holex thanks but your link refers to an implementation which may not be thread safe. Im looking for a correct version of the GCD code snippet I provided in the question. – banditKing Feb 03 '13 at 01:49
  • The correct version is given in the question here, along with explanation of why it is correct: http://stackoverflow.com/questions/9119042/why-does-apple-recommend-to-use-dispatch-once-for-implementing-the-singleton-pat. You should not override `alloc` unless you have a very, very strong reason to do so. – Rob Napier Feb 03 '13 at 01:53
  • Also here: http://www.mikeash.com/pyblog/friday-qa-2009-10-02-care-and-feeding-of-singletons.html – Rob Napier Feb 03 '13 at 01:56
  • @banditKing, that is totally thread-safe, you might have spotted the `@synchronized` keyword. – holex Feb 03 '13 at 01:59
  • @RobNapier, the reason is, we don't allow to create two or more instances of the singleton class, which would be purpose of the singleton classes. it is the very-very-very-strong reason to do it. – holex Feb 03 '13 at 02:02
  • I'm unclear: what's *not* thread-safe about dispatch_once? – KevinH Feb 03 '13 at 08:37
  • In other news, your dispatch_once call is referencing [super alloc]. How would your alloc override ever be called? – KevinH Feb 03 '13 at 08:38

1 Answers1

0

Why not just use +initialize?

static MyClass *gSingleton;

+(void) initialize {
  if ( self == [MyClass class] ) {
    gSingleton = [MyClass new];     
  }
}

+(MyClass*) getSingleton {
  return gSingleton;
}

It's thread-safe. The only issue is that it doesn't prevent someone from allocating a second object by using alloc/init or new.

EricS
  • 9,650
  • 2
  • 38
  • 34
  • 1
    There was a time when `+initialize` was good for this, but since the addition of `dispatch_once()`, that is the preferred way to do this. – Rob Napier Feb 03 '13 at 01:49
  • If it ain't broke, don't fix it! :-) – EricS Feb 03 '13 at 01:49
  • @EricS this may not be thread safe. Im looking for a GCD solution similar to the code I provided – banditKing Feb 03 '13 at 01:50
  • `dispatch_once` is much more readable. Note that even with `initialize`, you should never call the method "getSingleton". "Get" has a special meaning. It should be "sharedMyClass" – Rob Napier Feb 03 '13 at 01:50
  • @banditKing, `+initialize` is thread safe, but so is `dispatch_once`. – Rob Napier Feb 03 '13 at 01:51
  • 1
    BTW, by "more readable" I mean it puts all the related code in one place rather than spreading it over three different parts of the file (`initialize` may be doing other things as well, which makes this pattern muddy). – Rob Napier Feb 03 '13 at 01:55
  • @banditKing +initialize is thread-safe. Apple's documentation is very clear on that. – EricS Feb 03 '13 at 04:27
  • The code as written above is broken. As soon as MyClass has a subclass, + initialize will be called twice. dispatch_once is _the_ tool for doing things exactly once, so it is common sense to use it everywhere where things need doing exactly once. There are practical problems as well; you can't use class methods to tell the class what kind of singleton you create if you create it in + initialize. – gnasher729 Apr 04 '14 at 12:39
  • The code explicitly checks the class type - it is not broken at all. – EricS Apr 05 '14 at 01:59