Implement alloc on a singleton
我希望在我的系统中有一个singleton,但不希望呼叫者通过某种"sharedInstance"方法访问它,我希望他们能够不知道他们正在使用singleton,换句话说,我希望呼叫者能够说:
1 | MyClass *dontKnowItsASingleton = [[MyClass alloc] init]; |
为此,我尝试重写alloc,如下所示:
1 2 3 4 5 6 7 8 9 10 11 | // MyClass.m static MyClass *_sharedInstance; + (id)alloc { if (!_sharedInstance) { _sharedInstance = [super alloc]; } return _sharedInstance; } |
我的问题是:这样可以吗?它似乎有效,但我从未重写过alloc。另外,如果可以的话,我是否可以一直使用这种技术,而不是在我做过的一次调度方法?…
1 2 3 4 5 6 7 8 9 | + (id)sharedInstance { static SnappyTV *_sharedInstance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _sharedInstance = [[self alloc] init]; }); return _sharedInstance; } |
如@h2co3所述,您生产单件产品的方法是可以接受的,但不是螺纹安全。更传统的方法是将您的分配和比较包装在一个
如果有人来找我,我认为这里有一个整合了所有好建议的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | + (id)alloc { @synchronized(self) { if (!_sharedInstance) { _sharedInstance = [super alloc]; } return _sharedInstance; } } - (id)init { @synchronized(self) { static BOOL init = NO; if (!init) { init = YES; self = [super init]; } } return self; } |
多亏了@h2co3的线程安全问题,@codafi的线程安全处方,@rob mayoff的ARC下init的危险。今天我得到了最优秀和最聪明的人的帮助!
我认为您应该利用初始化方法:
1 2 3 4 5 6 7 8 9 10 | + (void) initialize { _sharedInstance= [[self alloc]init]; } + (id)sharedInstance { return _sharedIntsance; } |