Objective-C中的Singleton,与ARC和线程安全兼容 [英] Singleton in Objective-C, compatible with ARC and thread safe

查看:94
本文介绍了Objective-C中的Singleton,与ARC和线程安全兼容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想拥有一个线程安全的,与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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆