8

我看到了线程安全版本

+(MyClass *)singleton {
    static dispatch_once_t pred;
    static MyClass *shared = nil;

    dispatch_once(&pred, ^{
        shared = [[MyClass alloc] init];
    });
     return shared;
}

但是如果有人打电话会发生什么[MyClass alloc] init]?如何使其返回与+(MyClass *)singleton方法相同的实例?

4

3 回答 3

12

Apple 推荐这样严格的单例实现(不允许其他相同类型的活对象):

+ (instancetype)singleton {
    static id singletonInstance = nil;
    if (!singletonInstance) {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            singletonInstance = [[super allocWithZone:NULL] init];
        });
    }
    return singletonInstance;
}

+ (id)allocWithZone:(NSZone *)zone {
    return [self singleton];
}

- (id)copyWithZone:(NSZone *)zone {
    return self;
}

链接到苹果文档(页面底部,无 ARC)

于 2013-07-23T11:58:34.990 回答
2

这可能会有所帮助,

static Foo *sharedInstance = nil;

+ (Foo *)sharedInstance {

    if (sharedInstance == nil) {

        sharedInstance = [[super allocWithZone:NULL] init];
    }

    return sharedInstance;
}

+ (id)allocWithZone:(NSZone *)zone {
    @synchronized(self)
    {
        if (sharedInstance == nil) {
            sharedInstance = [super allocWithZone:zone];
            return sharedInstance;
        }
    }
    return nil;
}
于 2013-07-23T12:00:32.747 回答
0

我从鸭子博客中获取了这个代码示例: http ://www.duckrowing.com/2011/11/09/using-the-singleton-pattern-in-objective-c-part-2/

在 .h 我们有

@interface Foo : NSObject
+ (Foo *) sharedFoo;
@end

在 .m 我们有

static SLFoo *sharedInstance = nil;
static dispatch_queue_t serialQueue;

@implementation Foo

- (id)init
{
    id __block obj;

    dispatch_sync(serialQueue, ^{
        obj = [super init];
        if (obj) {
            ;
        }
    });

    self = obj;
    return self;
}

+ (Foo *) sharedFoo;
{
    static dispatch_once_t onceQueue;

    dispatch_once(&onceQueue, ^{
        if (sharedInstance) {
            return;
        }
        sharedInstance = [[Foo alloc]init];
    });
    return sharedInstance;

}

+ (id)allocWithZone:(NSZone *)zone
{
    static dispatch_once_t onceQueue;

    dispatch_once(&onceQueue, ^{
        serialQueue = dispatch_queue_create("com.mydomain.myApp.SerialQueueFoo", NULL);
        if (sharedInstance == nil) {
            sharedInstance = [super allocWithZone:zone];
        }
    });

    return sharedInstance;
}

@end

注意 allocWithZone。

于 2013-07-23T11:54:22.113 回答