1. 程式人生 > >(一二三)基於GCD的dispatch_once實現單例設計

(一二三)基於GCD的dispatch_once實現單例設計

super dispatch ret 強引用 一次 nslog span imp int

要實現單例,關鍵是要保證類的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

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

(一二三)基於GCD的dispatch_once實現單例設計