iOS 建立單例的兩種方法

建立一個單例不少辦法。我先列舉一個蘋果官方文檔中的寫法。安全

 

[cpp]  view plain copy
  1. static AccountManager *DefaultManager = nil;  
  2.    
  3. + (AccountManager *)defaultManager {  
  4.     if (!DefaultManager) DefaultManager = [[self allocWithZone:NULL] init];  
  5.     return DefaultManager;  
  6. }  


固然,在iOS4以後有了另一種寫法:多線程

 

 

[cpp]  view plain copy
  1. + (AccountManager *)sharedManager  
  2. {  
  3.         static AccountManager *sharedAccountManagerInstance = nil;  
  4.         static dispatch_once_t predicate;  
  5.         dispatch_once(&predicate, ^{  
  6.                 sharedAccountManagerInstance = [[self alloc] init];   
  7.         });  
  8.     return sharedAccountManagerInstance;  
  9. }  


該寫法具備如下幾個特性:app

 

1. 線程安全。函數

2. 知足靜態分析器的要求。oop

3. 兼容了ARCthis

 

而後我還有點好奇的是dispatch_once,這個函數,沒見過啊。spa

因而就到官方的文檔裏找找看,是怎麼說的。.net

下面是官方文檔介紹:線程

 

dispatch_once指針

Executes a block object once and only once for the lifetime of an application.

  void dispatch_once(

    dispatch_once_t *predicate,

    dispatch_block_t block);

Parameters

predicate

A pointer to a dispatch_once_t structure that is used to test whether the block has completed or not.

block

The block object to execute once.

Discussion

This function is useful for initialization of global data (singletons) in an application. Always call this function before using or testing any variables that are initialized by the block.

If called simultaneously from multiple threads, this function waits synchronously until the block has completed.

The predicate must point to a variable stored in global or static scope. The result of using a predicate with automatic or dynamic storage is undefined.

Availability

  • Available in iOS 4.0 and later.

Declared In

dispatch/once.h

 

咱們看到,該方法的做用就是執行且在整個程序的聲明週期中,僅執行一次某一個block對象。簡直就是爲單例而生的嘛。並且,有些咱們須要在程序開頭初始化的動做,若是爲了保證其,僅執行一次,也能夠放到這個dispatch_once來執行。

而後咱們看到它須要一個斷言來肯定這個代碼塊是否執行,這個斷言的指針要保存起來,相對於第一種方法而言,還須要多保存一個指針。

 

方法簡介中就說的很清楚了:對於在應用中建立一個初始化一個全局的數據對象(單例模式),這個函數頗有用。

若是同時在多線程中調用它,這個函數將等待同步等待,直至該block調用結束。

這個斷言的指針必需要全局化的保存,或者放在靜態區內。使用存放在自動分配區域或者動態區域的斷言,dispatch_once執行的結果是不可預知的。

 

 

總結:1.這個方法能夠在建立單例或者某些初始化動做時使用,以保證其惟一性。2.該方法是線程安全的,因此請放心大膽的在子線程中使用。(前提是你的dispatch_once_t *predicate對象必須是全局或者靜態對象。這一點很重要,若是不能保證這一點,也就不能保證該方法只會被執行一次。)

相關文章
相關標籤/搜索