Неожиданное поведение класса Singleton на iPhone, я делаю что-то не так?

StackOverflow https://stackoverflow.com/questions/1002364

  •  05-07-2019
  •  | 
  •  

Вопрос

Я реализую одноэлементный класс следующим образом:

static Singleton* _singletonInstance;

@implementation Singleton

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

+(Singleton*)instance
{
    return(_singletonInstance);
}
Инициализация

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

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

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

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

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

Это было полезно?

Решение

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

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

Другие советы

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

Я использую гораздо более сложную, но очень стабильную версию шаблона 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;
}

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top