利用dispatch_once建立单例

不管是爱仍是恨,你都须要单例。实际上每一个iOS或Mac OS应用都至少会有UIApplicationNSApplication.html

什么是单例呢?Wikipedia是如此定义的:设计模式

在软件工程中,单例是一种用于实现单例的数学概念,即将类的实例化限制成仅一个对象的设计模式。安全

或者个人理解是:app

单例是一种类,该类只能实例化一个对象。框架

    尽管这是单例的实际定义,但在Foundation框架中不必定是这样。好比NSFileMangerNSNotificationCenter,分别经过它们的类方法defaultManagerdefaultCenter获取。尽管不是严格意义的单例,这些类方法返回一个能够在应用的全部代码中访问到的类的共享实例。在本文中咱们也会采用该方法。函数

    使用Objective-C实现单例模式的最佳方式向来有不少争论,开发者(包括Apple在内)彷佛每几年就会改变他们的想法。当Apple引入了Grand Central Dispatch (GCD)(Mac OS 10.6和iOS4.0),他们也引入了一个很适合用于实现单例模式的函数。spa

    该函数就是dispatch_once.net

void dispatch_once( dispatch_once_t *predicate, dispatch_block_t block);

    该函数接收一个dispatch_once用于检查该代码块是否已经被调度的谓词(是一个长整型,实际上做为BOOL使用)。它还接收一个但愿在应用的生命周期内仅被调度一次的代码块,对于本例就用于shared实例的实例化。线程

dispatch_once不只意味着代码仅会被运行一次,并且仍是线程安全的,这就意味着你不须要使用诸如@synchronized 之类的来防止使用多个线程或者队列时不一样步的问题。设计

    Apple的GCD Documentation证明了这一点:

若是被多个线程调用,该函数会同步等等直至代码块完成。

    实际要如何使用这些呢?

    好吧,假设有一个AccountManager类,你想在整个应用中访问该类的共享实例。你能够按以下代码简单实现一个类方法:

+ (AccountManager *)sharedManager { 
    static AccountManager *sharedAccountManagerInstance = nil; 

    static dispatch_once_t predicate; dispatch_once(&predicate, ^{       
          sharedAccountManagerInstance = [[self alloc] init]; 
    });

    return sharedAccountManagerInstance; 

}

    这就意味着你任什么时候候访问共享实例,须要作的仅是:

AccountManager *accountManager = [AccountManager sharedManager];

    就这些,你如今在应用中就有一个共享的实例,该实例只会被建立一次。

    该方法有不少优点: 

           1 线程安全

           2 很好知足静态分析器要求

           3 和自动引用计数(ARC)兼容 

           4 仅须要少许代码

        该方法的劣势就是它仍然运行建立一个非共享的实例:

    AccountManager *accountManager = [[AccountManager alloc] init];

        有些时候你但愿有这种行为,但若是正在想要的是仅一个实例被实例化就须要注意这点。

    相关文章
    相关标签/搜索