Используйте Singleton In Interface Builder?

У меня синглтон настроен так:

static Universe *instance;

+ (Universe *)instance { return instance; }

+ (void)initialize
{
    static BOOL initialized = NO;
    if(!initialized)
    {
        initialized = YES;
        instance = [[Universe alloc] init];
    }
}

- (id) init
{
    self = [super init];
    if (self != nil) {
        self.showHistory = YES;
    }
    return self;
}

но теперь я понимаю, что хотел бы создать экземпляр из Interface Builder. Я думал просто врезаться в init метод, как так

    if (instance) 
         return instance;

Это плохая идея? Я бы предпочел, чтобы IB взял экземпляр, уже созданный в +initialize метод.

2 ответа

Решение

Это можно сделать. Об этом есть раздел в " Какао-дизайне " Бака и Яхтмана.

В вашем случае вы могли бы сделать что-то вроде:

static Universe *instance;

+ (Universe *)instance { return instance; }

+ (id)hiddenAlloc
{
  return [super alloc];
}

+ (id)alloc
{
  return [[self instance] retain];
}

+ (void)initialize
{
    static BOOL initialized = NO;
    if(!initialized)
    {
        initialized = YES;
        instance = [[Universe hiddenAlloc] init];
    }
}

- (id)init
{
  if(instance==nil) // allow only to be called once
  {
    // your normal initialization here
  }
  return self;
}

Код загрузки пера тогда правильно подберет синглтон через его вызов [[Universe alloc] init]и вы все еще можете использовать instance в вашем коде, как и раньше.

Книга содержит более подробную информацию и рекомендует реализацию new а также allocWithZone (оба просто как return [self alloc];), а также заглушки сообщения об ошибках, чтобы поймать copyWithZone а также mutableCopyWithZone попытки для хорошей меры.

Это будет течь. Вы можете сойти с рук, если вы измените его на:

if(instance) {
    [self release];
    return instance;
}

но это все еще пахнет немного для меня. Мне любопытно, что вы используете для одиночных игр в IB; Я подозреваю, что я бы избежал этой конструкции в моем коде.

Другие вопросы по тегам