4

I'd like to have a singleton in my system but rather than have callers access it via some kind of 'sharedInstance' method, I'd like them to be able to be unaware that they are using a singleton, in other words, I'd like the callers to be able to say:

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

To accomplish this, I've tried overriding alloc as follows:

// MyClass.m

static MyClass *_sharedInstance;

+ (id)alloc {

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

My question is: is this okay? It seems to work, but I've never overridden alloc before. Also, if it's okay, could I always use this technique, rather than dispatch_once approach I have been doing? ...

+ (id)sharedInstance {

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

3 回答 3

5

正如@H2CO3 提到的,您制作单例的方法是可以接受的,但不是线程安全的。更传统的方法是将您的分配和比较包装在一个@synchronized块中,以减少多线程访问,但是覆盖+alloc并不是实现已经摇摇欲坠的模式的最佳方式。

于 2012-12-22T21:02:03.523 回答
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 解决 init under arc 的危险。我今天得到了最优秀和最聪明的人的帮助!

于 2012-12-22T22:40:13.783 回答
1

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

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


+ (id)sharedInstance 
{
    return _sharedIntsance;
}
于 2012-12-22T21:09:06.757 回答