创建单例

背景

很多时候,我们在网上,或者开源项目中,看到类似下面这样创建一个单例:

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

    if(shared == nil) {
        shared = [[MyClass alloc] init];
    }
    return shared;
}

但是,上面的代码在很多层面是错误的。首先,它不是线程安全的,当多个线程调用这个创建方法时,我们无法确保正确创建了一个实例,有时在苹果的官方例子中也是这么写的。

如果你必须使用单例,可以使用dispatch_once()

dispatch_once() 安全地解决了上面存在的问题:

(1)它保证了在块中的代码将在应用中只调用一次

(2)它是线程安全的

(3)它比使用其他方法创建单例更快,比如使用@synchronize()

@implementation Singleton
static Singleton *shareSingleton = nil;

+(Singleton*) shareInstance {
    @synchronized(self){  //加锁
        if (shareSingleton == nil) {
            shareSingleton = [[Singleton alloc] init];  
        }
    }
    return shareSingleton;
}

最佳实践

所以,创建单例的最佳实践应该是:

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

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

总结

在实际项目中,我们应该尽量避免过多使用单例,虽然单例不是什么魔鬼,但是能不用就不用。如果你必须使用单例,也要使用正确的方法来创建它。

posted @ 2014-02-20 11:38  剑尖  阅读(182)  评论(0编辑  收藏  举报