Неожиданное поведение класса Singleton на iPhone, я делаю что-то не так? - PullRequest
1 голос
/ 16 июня 2009

Я реализую синглтон-класс следующим образом:

static Singleton* _singletonInstance;

@implementation Singleton

+(void)initialize
{ 
    _singletonInstance = [[Singleton alloc] init]; 
}

+(Singleton*)instance
{
    return(_singletonInstance);
}

initialize вызывается только при первом вызове экземпляра. Затем у меня есть метод, который я могу вызвать для установки некоторых переменных экземпляра. Так что в итоге это выглядит так.

_singleton = [Singleton instance];
[_singleton setupWithParams: blah];

Когда я получаю экземпляр этого синглтона внутри объекта, он отлично работает в первый раз; Однако после того, как я освобождаю и создаю новую копию объекта, которому нужен экземпляр синглтона, я получаю ошибку BAD ACCESS, когда пытаюсь вызвать функцию установки.

Просто чтобы проверить вещи, я распечатываю адрес экземпляра перед тем, как сделать вызов установки, и оба раза они сообщают об одном и том же адресе, но когда я проверяю журнал ошибок для вызова BAD ACCESS, в нем перечисляется совершенно другой адрес памяти.

У кого-нибудь есть идеи, почему этот указатель на экземпляр выглядит нормально, когда я его печатаю, но когда я обращаюсь к нему, он, по-видимому, указывает на случайные данные?

Ответы [ 4 ]

3 голосов
/ 16 июня 2009

Значение указателя выглядит допустимым, потому что раньше оно было, но, скорее всего, память была свободна, поэтому то, на что оно указывает, выглядит как случайные данные.

Вы получили одну ссылку с вашим [[Singleton alloc] init] выше, но есть ли release где-то еще, что может выполняться? Держу пари, твой код звонит instance, а потом release, хотя твой код никогда не получал ссылку. И это не должно быть необходимо для синглтона в любом случае. Просто предположение ...

1 голос
/ 17 июня 2009

Код Валерия лучше для реализации синглтона, но проблема почти наверняка в том, что код, который вызывает [экземпляр Синглтона], работает так, как если бы он имел право собственности, фактически не переходя во владение, используя retain, а затем выпускает его позже. *

Найдите там свою ошибку и прочитайте Правила управления памятью .

Кроме того, в Xcode включает NSZombieEnabled , и консоль покажет вам, когда вы попытаетесь сообщить объекту после его освобождения.

1 голос
/ 16 июня 2009

Я использую гораздо более сложную, но очень стабильную версию шаблона Singleton (взято с описанием из Брэндона "Quazie" Kwaselow Blog ):

static SampleSingleton *sharedSampleSingletonDelegate = nil;

+ (SampleSingleton *)sharedInstance {
   @synchronized(self) {
      if (sharedSampleSingletonDelegate == nil) {
         [[self alloc] init]; // assignment not done here
      }
   }
   return sharedSampleSingletonDelegate;
}

+ (id)allocWithZone:(NSZone *)zone {
   @synchronized(self) {
      if (sharedSampleSingletonDelegate == nil) {
         sharedSampleSingletonDelegate = [super allocWithZone:zone];
         // assignment and return on first allocation
         return sharedSampleSingletonDelegate;
      }
   }
   // on subsequent allocation attempts return nil
   return nil;
 }

- (id)copyWithZone:(NSZone *)zone
{
   return self;
}

- (id)retain {
   return self;
}

- (unsigned)retainCount {
   return UINT_MAX;  // denotes an object that cannot be released
}

- (void)release {
   //do nothing
}

- (id)autorelease {
   return self;
}
1 голос
/ 16 июня 2009

Вы где-нибудь снимаете свой _singletonInstance?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...