创建单例

背景

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

+(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;
}

总结

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

最近的文章

Controls

UIActivityIndicatorViewself.activity.color = [UIColor yellowColor];self.activity.backgroundColor = [UIColor colorWithWhite:0.2 alpha:0.4];self.activity.layer.cornerRadius = 10;CGRect f = self.activity.bounds;f.size.width += 10;f.size.height += 10;...…

iOS继续阅读
更早的文章

不同行高的 table view cell

本文翻译自:Table View Cells With Varying Row Heights更新:可以看看这篇文章,介绍在iOS8下如何实现自动调整大小的Cell。我发布了几篇关于处理动态类型的文章,其中包括根据字体大小的变化,改变表视图的行高度。但是这些都是假定在表视图中单元行高都是一样的。在这篇文章中,我将讲解,通过使用自动布局来设置不同的行高。在开始之前,我需要感谢Amy Worrall写的using auto layout to calculate table cell he...…

iOS继续阅读