// See Mike Ash "Care and Feeding of Singletons"
// See Cocoa Samurai "Singletons: You're doing them wrong"
+(MySingleton *)singleton {
static dispatch_once_t pred;
static MySingleton *shared = nil;
dispatch_once(&pred, ^{
shared = [[MySingleton alloc] init];
shared.someIvar = @"blah";
});
return shared;
}
Имейте в виду, что dispatch_once не является повторно входящим , поэтому вызов себя изнутри блока dispatch_once приведет к блокировке программы.
Не пытайтесь защищать себя от кода.Если вы не программируете фреймворк, относитесь к своему классу как к нормальному, а затем придерживайтесь единой идиомы выше.Думайте об идиоме синглтона как об удобном методе, а не как об определяющей черте вашего класса.Вы хотите относиться к своему классу как к нормальному классу во время модульного тестирования, поэтому можно оставить доступный конструктор.
Не беспокойтесь об использовании allocWithZone:
- Он игнорирует свои аргументы и ведет себя точно так же, как
alloc
.Зоны памяти больше не используются в Objective-C, поэтому allocWithZone:
сохраняется только для совместимости со старым кодом. - Это не работает.Вы не можете применить одноэлементное поведение в Objective-C, потому что всегда можно создать больше экземпляров, используя
NSAllocateObject()
и class_createInstance()
.
Метод фабрики-одиночки всегда возвращает один из этих трех типов:
id
, чтобы указать, что возвращаемый тип не полностью известен (случай, когда вы создаете классcluster). instancetype
, чтобы указать, что возвращаемый тип является экземпляром включающего класса. - Само имя класса (
MySingleton
в примере), чтобы упростить его.
Поскольку вы пометили эту iOS, альтернативой синглтону является сохранение ивара в приложение.делегировать, а затем использовать вспомогательный макрос, который вы можете переопределить, если передумаете:
#define coreDataManager() \
((AppDelegate*)[[UIApplication sharedApplication] delegate]).coreDataManager