В общем случае ваш конструктор не должен обеспечивать единичность. Ваш instance
метод должен (что он делает). Причина этого в том, что вам может понадобиться один объект и возможность создавать другие экземпляры объекта.
Что касается предоставленного вами кода, то init
не является поточно-ориентированным. Можно было бы назначить два отдельных потока на gInstance
. Поток, который устанавливает его первым, будет пропускать память. И другие тонкие ошибки могут привести. Например, если синглтон был своего рода общим хранилищем данных, поток, выигравший гонку, фактически потерял бы свои данные относительно остальной части программы.
Причина, по которой я упоминаю о безопасности потоков, заключается в том, что лично я столкнулся со многими ошибками, связанными с тем, что синглтоны используются в многопоточных приложениях небезопасными способами. Поэтому создание синглтонов может быть небезопасным, если вы абсолютно уверены, что это не будет проблемой.
С точки зрения того, как реализовать это потокобезопасным способом, я видел, что один из двух говорит:
// first way
+ (Deck *)instance {
static dispatch_once_t onceToken;
static Deck *_shared;
dispatch_once(&onceToken, ^{
_shared = [[Deck alloc] init];
});
return _shared;
}
// second way
+ (Deck *)instance {
static Deck *_shared;
@synchronized(self) {
if (_shared == nil) {
_shared = [[Deck alloc] init];
}
}
return _shared;
}
// init method
- (id)init {
if ((self = [super init])) {
// init stuff
}
return self;
}
Для использования dispatch_once
требуется libdispatch, что означает минимальную ОС iOS 4.0 или OS X 10.6. Использование @synchronized(self)
до этого должно работать на ОС.