天天看點

(一二三)基于GCD的dispatch_once實作單例設計

要實作單例,關鍵是要保證類的alloc和init隻被調用一次,并且被自身強引用防止釋放。

近日讀唐巧先生的《iOS開發進階》,受益匪淺,通過GCD實作單例就是收獲之一,下面把這個方法與大家分享。

在GCD中,有一個函數dispatch_once,可以實作代碼段的一次性執行,和static修飾的變量指派的一次性一樣,我們結合static和dispatch_once,就可以簡單的實作單例。

下面的代碼實作了SomeClass單例:

#import <Foundation/Foundation.h>

@interface SomeClass : NSObject

+ (SomeClass *)sharedInstance;

@end
           
#import "SomeClass.h"

@implementation SomeClass

+ (SomeClass *)sharedInstance{
    
    static id sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
    });
    
    return sharedInstance;
    
}

@end
           

下面解釋一下這段代碼。

第一句建立一個sharedInstance靜态強指針,是為了指向建立好的單例,防止其釋放,隻有第一次進入的時候指針被指派為nil。

一定注意dispatch_once_t變量必須是靜态,它的值用于判斷是否已經執行一次。

第二句和dispatch_once是固定用法,這樣可以實作block内的代碼一次性執行,也就是說隻有第一次調用這個方法時才會執行個體化類,之後都是傳回指針指向的值。

最後傳回指針,就相當于拿到了單例。

對單例的運作結果進行驗證:

我們多次擷取單例對象并且列印位址,可以發現位址是一樣的。

#import "ViewController.h"
#import "SomeClass.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    SomeClass *sc1 = [SomeClass sharedInstance];
    SomeClass *sc2 = [SomeClass sharedInstance];
    SomeClass *sc3 = [SomeClass sharedInstance];
    NSLog(@"%p %p %p",sc1,sc2,sc3);
    
}

@end
           
2015-08-17 20:59:22.139 基于GCD實作單例[2785:31918] 0x7fb40af11b90 0x7fb40af11b90 0x7fb40af11b90
           

通過這種方式,簡單高效的實作了單例,值得使用。