Objective-C中的Singleton,与ARC和线程安全兼容 [英] Singleton in Objective-C, compatible with ARC and thread safe
问题描述
我想拥有一个线程安全的,与ARC兼容的单例,但在我看来,这是我找到的最常见的单例示例,此示例粘贴在这里:
I want to have a thread safe, ARC compatible singleton, but is seems to me that the most common example of singleton that I find, an example pasted here:
+ (MyClass *)sharedInstance
{
static MyClass *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
// Do any other initialisation stuff here
});
return sharedInstance;
}
不会阻止其他开发人员调用[[MyClass alloc] init]并覆盖所需的流程. 处理它的正确方法是什么(除了在init中引发异常)?
doesn't stops other developer from calling [[MyClass alloc] init] and overriding the desired flow. What is the proper way to handle it (apart from throwing exception in init)?
推荐答案
您还必须重写+alloc
方法,以避免分配多个单例实例.
you also have to override the +alloc
method to avoid to allocate more than one instance of the singleton.
EDIT#3: 好吧,我真的知道官方文档中关于覆盖 +alloc
方法的内容,但是要获得所要求的利益,没有办法避免.我个人不同意这样做,但是它可以提供所需的结果.
EDIT#3: well, I really know what the official documentation says about overriding the +alloc
method, but to achieve the asked benefit there is no way to avoid it. personally I don't agree to do it but it can provide the desired result.
是这样的:
static MyClass *_sharedInstance = nil;
static BOOL _bypassAllocMethod = TRUE;
+ (id)sharedInstance {
@synchronized([MyClass class]) {
if (_sharedInstance == nil) {
_sharedInstance = [[MyClass alloc] init];
}
}
return _sharedInstance;
}
+ (id)alloc {
@synchronized([MyClass class]) {
_bypassAllocMethod = FALSE; // EDIT #2
if (_sharedInstance == nil) {
_sharedInstance = [super alloc];
return _sharedInstance;
} else {
// EDIT #1 : you could throw an exception here to avoid the double allocation of the singleton class
@throw [NSException exceptionWithName:[NSString stringWithFormat:@"<%@: %p> Double allocation issue", [_sharedInstance class], _sharedInstance] reason:@"You cannot allocate the singeton class twice or more." userInfo:nil];
}
}
return nil;
}
// EDIT #2 : the init method
- (id)init {
if (_bypassAllocMethod)
@throw [NSException exceptionWithName:@"invalid allocation" reason:@"invalid allocation" userInfo:nil];
if (self = [super init]) {
}
return self
}
编辑#1
您绝对不需要在这里引发异常,但是对于开发人员以错误的方式使用您的类的开发人员而言,与返回简单的nil
指针相比,这是更多的视觉反馈.
you don't definitely need to throw an exception here but it is much more visual feedback for the developers of they use your class in wrong way, than sending back a simple nil
pointer.
编辑#2
我添加了一个简单的技巧,以避免开发人员实例化该类以绕过修改的+alloc
方法,在这种情况下,分配会很好,但-init
会引发异常.
I've added a simple trick to avoid the developers instantiate the class to bypass the modified +alloc
method, in that case the allocation will work well but the -init
will throw an exception.
这篇关于Objective-C中的Singleton,与ARC和线程安全兼容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!