Что-нибудь может пойти не так, когда я использую static для реализации синглтона? - PullRequest
2 голосов
/ 02 февраля 2012

Я реализую одноэлементный класс (и давайте не будем вступать в обсуждение, если это неправильно или нет).У меня есть метод для получения экземпляра этого класса, который лениво инициализируется:

+ (FFDataManager *)sharedDataManager {
  static FFDataManager *dm = nil;
  if (!dm) {
    dm = [[FFDataManager alloc] init];
  }

  return dm;
}

Есть ли что-то, на что я должен обращать внимание при выполнении этого с использованием static (внутри метода), а несоздание глобальной переменной?Что-нибудь может пойти не так, все учебники в Интернете используют глобальную переменную.

Ответы [ 3 ]

6 голосов
/ 02 февраля 2012

Моя предпочтительная реализация синглтона выглядит так:

+ (MyClass *) sharedInstance {
    static dispatch_once_t predicate = 0;
    __strong static MyClass *shared = nil;

    dispatch_once(&predicate, ^{
        shared = [[self alloc] init];
    });

    return shared;
}

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

1 голос
/ 02 февраля 2012

Чтобы ответить на оригинальный вопрос (у других есть адрес, лучший способ выполнить инициализацию):

Есть ли что-то, на что я должен обращать внимание при выполнении статического (внутри метода) метода в отличие от создания глобальной переменной?

номер

Разница превышает видимость , а не срок службы .

  • Глобальное (со статическим или без него) время жизни - это время выполнения приложения.
  • Глобальный без static является видимым во всем приложении. На него можно ссылаться из любого другого места, называя его в операторе extern.
  • Глобал с static виден видимым только в блоке компиляции (который обычно представляет собой один файл, но #import / #include может изменить это).
  • Переменная, объявленная в функции / методе как static, является глобальной переменной, которая только видима в этой функции / методе.

Если вы используете глобал только в одной функции, то вы сделали хорошо - она ​​ограничивает видимость только тем местом, где она требуется, сохраняя при этом время жизни выполнения. Любой инициализатор запускается один раз, как и для глобальных файловых уровней.

0 голосов
/ 02 февраля 2012

То, что вы создаете, является статической локальной переменной.Статические локальные переменные сохраняют свое значение посредством последовательных вызовов методов.К ним можно получить доступ только из метода, в котором они определены. Когда приложения запускаются, статические локальные переменные устанавливаются на 0 один раз.

Так что, по моему мнению, вы делаете с каждым вызовом sharedDataManager, который вы объявляетеновую статическую локальную переменную и установите для нее nil.Я не думаю, что это необходимо или даже хорошо.И также каждый раз, когда if (!dm) проверяет dm, это nil, потому что вы устанавливаете dm на ноль строки раньше.

Я бы пошел со статическим глобальным подходом.Посмотрите на http://www.johnwordsworth.com/2010/04/iphone-code-snippet-the-singleton-pattern/

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