2

i don't understand the use of NSAssert in +alloc, as when +alloc is called from +sharedGameManager, the static _sharedGameManager variable is nil (so NSAssert should stop execution the first time [self alloc] init] is called...)

+(GameManager*)sharedGameManager {
    @synchronized([GameManager class])                             
    {
        if(!_sharedGameManager)                                    
            [[self alloc] init]; 
        return _sharedGameManager;                                 
    }
    return nil; 
}

+(id)alloc 
{
    @synchronized ([GameManager class])                            
    {
        NSAssert(_sharedGameManager == nil,
                 @"Attempted to allocated a second instance of the Game Manager singleton");
        _sharedGameManager = [super alloc];
        return _sharedGameManager;                                 
    }
    return nil;  
}

Thanks for your answer

Paul
  • 6,108
  • 14
  • 72
  • 128

3 Answers3

3

Are you thinking of NSAssert the wrong way round?

NSAssert( _sharedGameManager==nil, @"Attempted to …");

Will throw an Exception if _sharedGameManager is not nil. It Asserts that the expression is TRUE, it says "I assert that this must be the case", therefore _sharedGameManager must be nil, or an exception is raised. This could only happen if you tried to create 2 instances of this Class.

hooleyhoop
  • 9,128
  • 5
  • 37
  • 58
0

This looks like a couple of snippets glued together; alloc is an instance method, not a class method (static). If you want to perform initialization of a singleton class, use +(void)initialize

The Objective-C runtime claims to guarantee this class method only gets executed once, so it is an effective mechanism for setting up a singleton. For further reading, hit up Mike Ash's blog post on the topic.

wobbals
  • 374
  • 3
  • 8
  • 1
    `+alloc` _is_ a class method. Otherwise, you're right - it does seem Paul just has two unrelated snippets put together. Everyone really needs to use `dispatch_once` to create singletons, and not the pattern given by Apple. – Itai Ferber Apr 19 '12 at 22:15
  • @wobbals : thanks wobbals, alright thanks for the tips, i found this code in a book, what do you think about this NSAssert? is it a mistake? can it work like that? if so, i would not understand why – Paul Apr 19 '12 at 22:45
  • Hmm, it really doesn't look anything like two unrelated snippets. Both methods could only ever work in the presence of each other. – hooleyhoop Apr 19 '12 at 23:16
  • @hooleyhoop You're right, I wasn't clear in my thinking when I glanced at this code. You _can_ implement the singleton without overriding alloc (as in the Mike Ash example), but there are clearly multiple acceptable approaches. – wobbals Apr 24 '12 at 18:11
0

There's a better way to guarantee the behavior you want, through Grand Central Dispatch:

+ (GameManager *)sharedGameManager {
    static GameManager *sharedGameManager = nil;
    static dispatch_once_t token;
    dispatch_once(&token, ^{
        sharedGameManager = [[GameManager alloc] init];
    });

    return sharedGameManager;
}

dispatch_once is guaranteed to be run only once, so your game manager won't be over-initialized. As long as you don't release it, it will stay alive, and it will correctly be released at the end of your program (because of its static context).

Itai Ferber
  • 28,308
  • 5
  • 77
  • 83
  • @RichardJ.RossIII Oy, you're right. I was reading too quickly, and mixed things up in my head. You're totally right. Whoops. – Itai Ferber Apr 19 '12 at 22:30
  • 1
    @RichardJ.RossIII Anyway, updated my answer to remove that bit. – Itai Ferber Apr 19 '12 at 22:34
  • @Itai Ferber : thanks for the answer, i'll use this way, i was still wondering why the code used NSAssert, which seems (to me) to block the code, do you have any idea about that? – Paul Apr 19 '12 at 22:48