Objective-C singleton pattern в iOS 5+
Я читал много потоков и статей в блогах о том, как реализовать singleton в objective-c, некоторые из них, возможно, немного устарели (год 2010 или ранее), и кажется, что у людей разные мнения относительно эта проблема... Имеет ли Apple документацию о внедрении синглета? Я не мог найти его. Если да, может кто-нибудь сказать мне, где?
Мне нужен синглтон для класса, который имеет как публичные, так и частные переменные. В настоящее время это реализация, которую я имею для такого класса:
@interface MySingleton ()
@property (strong, nonatomic) NSString *state;
@end
@implementation MySingleton
@synthesize state = _state;
@synthesize count = _count;
static MySingleton *sharedObject = nil;
+ (MySingleton *)sharedInstance
{
static dispatch_once_t _singletonPredicate;
dispatch_once(&_singletonPredicate, ^{
sharedObject = [[super allocWithZone:nil] init];
});
return sharedObject;
}
+ (id)allocWithZone:(NSZone *)zone
{
return [self sharedInstance];
}
Должен ли это быть рекомендованным способом? И как мне инициализировать переменные экземпляра, общедоступные и частные?
Еще одна проблема, которую я хотел бы прояснить в отношении синглтона: будет ли это причиной утечки памяти? Является ли использование синглтонов действительно рекомендуемым в iOS?
Спасибо
Ответы
Ответ 1
Вышеуказанное верно, а также комментарий @miho о включении статического объекта внутри метода sharedInstance. Но нет оснований переопределять +allocWithZone:
. Синглтоны в ObjC обычно "разделяются", а не принудительно. Вы можете создавать другие экземпляры "singleton". Если это незаконно для создания других экземпляров, вы должны сделать init
выполнить NSAssert
, а не обманывать вызывающего абонента в +allocWithZone:
. Если ваш синглтон изменен (и большинство из них), вы абсолютно не должны переопределять +allocWithZone:
таким образом.
Еще одна проблема, которую я хотел бы прояснить в отношении singleton: будет ли это причиной утечки памяти?
Нет. Этот объект никогда не будет выпущен, но он всегда будет доступен. Это не утечка.
Является ли использование синглтонов, действительно рекомендованных в iOS?
Да, и это очень распространенный шаблон, используемый во всех фреймах Cocoa. Тем не менее, существуют различные другие шаблоны, которые в последнее время стали несколько популярными среди разработчиков. Зависимость Инъекции вызывает некоторый интерес, хотя я не вижу его на практике очень часто. Снижение зависимости от синглтонов может улучшить тестируемость, и я недавно экспериментировал с тем, как некоторые из них в моем коде с некоторым успехом. Но у них долгая, гордая история в Cocoa, и я не считаю их проблемой.
EDIT: у вас есть одна ошибка в коде. Вы должны называть [[self alloc] init]
, а не [[super alloc] init]
. Нет причин когда-либо называть +allocWithZone:
, просто используйте +alloc
. (Время, когда методы ...WithZone:
были полезны, уже давно прошло.)
Ответ 2
В Xcode в разделе "Поиск документации" введите Создание экземпляра Singleton. Есть много результатов (но ссылка выше, внизу страницы, имеет пример кода).
Ответ 3
Да, это рекомендуемый способ. Существует только одна небольшая разница в том, как я ее использую: я определяю sharedObject
как статическую переменную внутри метода + (MySingleton *)sharedInstance
, потому что не должно быть возможности получить доступ к переменной из любого другого места, затем из метода getter.
И нет, вы не создадите утечку памяти. Когда ваше приложение будет прекращено, вся зарезервированная память, используемая вашим приложением, будет выпущена в любом случае, и нет другой ситуации, когда должен быть выпущен статический общий экземпляр. В области pre-ARC даже было принято переопределять метод release
, чтобы предотвратить случайное освобождение объекта.
Ответ 4
Немного предупреждения с использованием gcd для одиночных чисел:
dispatch_once(&_singletonPredicate, ^{
sharedObject = [[super allocWithZone:nil] init];
});
Если метод init по какой-либо причине обращается к объекту singleton прямо или косвенно, произойдет тупик. По этой причине я считаю, что более подходящий способ написать синглтон - через
+ (void) initialize
Метод
Ответ 5
Я все еще использую заголовок singleton из CocoaWithLove - может быть немного устаревшим, но все же работает как шарм. Он в основном делает то же, что описано здесь, ссылаясь на документацию на яблоки, и я бы предположил, по крайней мере, документацию Apple (внизу этой страницы). Есть люди, полагая, что он останется действительным на неопределенный срок. Это официальное решение, предложенное Apple.