在单例上实现alloc

时间:2012-12-22 20:54:48

标签: objective-c ios

我想在我的系统中有一个单例,但不是让调用者通过某种'sharedInstance'方法访问它,我希望他们能够不知道他们正在使用单例,在其他话说,我希望来电者能够说:

MyClass *dontKnowItsASingleton = [[MyClass alloc] init];

为了实现这一点,我尝试重写alloc,如下所示:

// MyClass.m

static MyClass *_sharedInstance;

+ (id)alloc {

    if (!_sharedInstance) {
        _sharedInstance = [super alloc];
    }
    return _sharedInstance;
}

我的问题是:这没关系吗?它似乎工作,但我从来没有覆盖alloc。另外,如果没关系,我可以一直使用这种技术,而不是我一直在做的dispatch_once方法吗? ...

+ (id)sharedInstance {

    static SnappyTV *_sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[self alloc] init];
    });
    return _sharedInstance;
}

3 个答案:

答案 0 :(得分:5)

正如@ H2CO3所提到的,你开始生产单身人士的方法是可以接受的,但不是线程安全的。更传统的方法是在@synchronized块中包装您的赋值和比较,以便减少多线程访问,但是覆盖+alloc不是实现已经不稳定模式的最佳方式。

答案 1 :(得分:1)

我认为你应该利用初始化方法:

+ (void) initialize
{
    _sharedInstance= [[self alloc]init];
}


+ (id)sharedInstance 
{
    return _sharedIntsance;
}

答案 2 :(得分:1)

如果其他人来看,这是一个我认为整合了所有好建议的解决方案:

+ (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的危险。今天我得到了最优秀和最聪明的帮助!