2012-04-19 2 views
2

я не понимаю, использование NSAssert в +alloc, а когда +alloc вызывается из +sharedGameManager, статическая _sharedGameManager переменная nil (так NSAssert должен остановить выполнение в первый раз [self alloc] init] называется ...)NSAssert in Singleton: почему этот код действителен?

+(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; 
} 

Спасибо за ваш ответ

ответ

3

Вы думаете о том, что NSAssert ошибочно?

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

сгенерирует исключение, если _sharedGameManager не ноль. Он утверждает, что выражение TRUE, в нем говорится: «Я утверждаю, что это должно быть так», поэтому _sharedGameManager должно быть nil, или возникает исключение. Это может произойти только в том случае, если вы попытались создать 2 экземпляра этого класса.

+0

О, да, правда, я не понимаю, почему я был уверен, что это было наоборот :) спасибо за ответ! – Paul

0

Это похоже на пару фрагментов, склеенных вместе; alloc - это метод экземпляра, а не метод класса (статический). Если вы хотите выполнить инициализацию одноэлементного класса, используйте +(void)initialize

Заявки на выполнение Objective-C, которые гарантируют, что этот метод класса выполняется только один раз, поэтому он является эффективным механизмом для настройки Singleton. Для дальнейшего чтения, нажмите blog post Майка Эша на эту тему.

+1

'+ alloc' _is_ метод класса. В противном случае вы правы - похоже, у Пола только два несвязанных фрагмента. Каждому действительно нужно использовать 'dispatch_once' для создания синглетонов, а не шаблон, данный Apple. –

+0

@wobbals: спасибо wobbals, хорошо спасибо за советы, я нашел этот код в книге, что вы думаете об этом NSAssert? это ошибка? может ли он работать так? если да, я бы не понял, почему – Paul

+0

Хм, это действительно не выглядит как два несвязанных фрагмента. Оба метода могли работать только в присутствии друг друга. – hooleyhoop

0

Там есть лучший способ гарантировать поведение, которое вы хотите, через Диспетчер Grand Central:

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

    return sharedGameManager; 
} 

dispatch_once гарантированно будет работать только один раз, так что ваш менеджер игра не будет закончена инициализирован. Пока вы его не выпускаете, он останется в живых, и он будет правильно выпущен в конце вашей программы (из-за его контекста static).

+0

Вы, очевидно, не понимаете, как работает NSAssert ... –

+0

@ RichardJ.RossIII Oy, вы правы. Я читал слишком быстро и смешивал вещи в голове. Вы совершенно правы. Упс. –

+1

@ RichardJ.RossIII В любом случае, обновил мой ответ, чтобы удалить этот бит. –

Смежные вопросы