2012-01-09 33 views
11

您好我有iOS版的一個單例的實現以前的版本如下:iOS 5中的單身?

.h文件中

@interface CartSingleton : NSObject 
{ 

} 
+(CartSingleton *) getSingleton; 

.m文件

@implementation CartSingleton 

static CartSingleton *sharedSingleton = nil; 

+(CartSingleton *) getSingleton 
{ 
    if (sharedSingleton !=nil) 
     { 
     NSLog(@"Cart has already been created....."); 
     return sharedSingleton; 
     } 
    @synchronized(self) 
    { 
    if (sharedSingleton == nil) 
     { 
     sharedSingleton = [[self alloc]init]; 
     NSLog(@"Created a new Cart"); 
     } 
    } 
    return sharedSingleton; 
} 
//============================================================================== 
+(id)alloc 
{ 
    @synchronized([CartSingleton class]) 
    { 
    NSLog(@"inside alloc"); 
    NSAssert(sharedSingleton == nil, @"Attempted to allocate a second instance of a singleton."); 
    sharedSingleton = [super alloc]; 
    return sharedSingleton; 
    } 

    return nil; 
} 

//============================================================================== 
-(id)init 
{ 
    self = [super init]; 
} 

但是網絡我看到人們已實施使用此代碼的Singleton設計模式:

+ (id)sharedInstance 
{ 
    static dispatch_once_t pred = 0; 
    __strong static id _sharedObject = nil; 
    dispatch_once(&pred, ^{ 
    _sharedObject = [[self alloc] init]; // or some other init method 
    }); 
    return _sharedObject; 
} 

有經驗的人請指導我。 我是一個新手,徹底混淆了Singleton和舊的iOS的舊的實現,哪個是正確的?

非常感謝

+0

見http://stackoverflow.com/questions/5720029/create-singleton-using-gcds-dispatch-once-in-objective-c更現代的,更簡單但仍然線程安全。 – 2012-01-09 23:18:47

回答

19

嚴格地說,你必須使用:

+ (MySingleton*) instance { 
    static dispatch_once_t _singletonPredicate; 
    static MySingleton *_singleton = nil; 

    dispatch_once(&_singletonPredicate, ^{ 
     _singleton = [[super allocWithZone:nil] init]; 
    }); 

    return _singleton; 
} 

+ (id) allocWithZone:(NSZone *)zone { 
     return [self instance]; 
} 

現在你保證一個不能調用分配/ init和創建另一個實例。

說明:實例方法處於類級別,是獲取對單例的引用的主要訪問方法。該方法只使用dispatch_once()內置隊列,該隊列只執行一次塊。運行時如何保證塊只執行一次?使用您提供的謂詞(類型爲dispatch_once_t)。這個低級調用將保證即使有多個線程試圖調用它,只有一個線程成功,其他線程會一直等到第一個線程完成並返回。

我們重寫allocWithZone的原因是因爲alloc調用allocWithZone作爲區域傳遞nil(默認區域)。爲了防止流氓代碼分配和初始化另一個實例,我們重寫allocWithZone,以便傳回的實例是已經初始化的單例。這可以防止創建第二個實例。

+1

有人可以更詳細地解釋此代碼以改善答案嗎? – djskinner 2012-08-12 21:47:00

+0

希望解釋有幫助。否則,請提出具體問題的澄清。 – 2012-08-20 15:07:26

+0

非常好,謝謝。 – djskinner 2012-08-21 08:40:03

9

的dispatch_once片段是功能上等同於另一個。你可以在http://developer.apple.com/library/mac/#documentation/Darwin/Reference/Manpages/man3/dispatch_once.3.html閱讀。

這是我使用的單身:

+ (MySingleton*) getOne { 
    static MySingleton* _one = nil; 

    @synchronized(self) { 
     if(_one == nil) { 
      _one = [[ MySingleton alloc ] init ]; 
     } 
    } 

    return _one; 
} 

注意:在大多數情況下,你甚至不需要使用@Synchronized(但它是安全的這樣)。

+1

塊也適用於iOS 4。 – 2012-01-09 23:26:10

+0

+ Peter DeWeese - 你是對的。我的錯。 – 2012-01-09 23:33:30

+0

如果你沒有在其他地方使用@syncrhonized,這會導致大量的開銷來處理ObjectiveC異常 - 所以如果你不使用它們,你應該使用選擇的答案和塊版本。 – 2013-03-12 19:51:21

0

單例是一種特殊的類,其中只有當前進程的類的一個實例存在。 (對於iPhone應用程序,一個實例在整個應用程序中共享。)UIKit中的一些示例是[UIApplication sharedApplication](它返回應用程序本身的唯一實例)和[NSFileManager defaultManager](它返回文件管理器實例)。單身人士可以成爲在整個應用程序中共享數據和常用方法的簡單方法。

而不是使用alloc/init創建單例類的實例,您將調用一個將返回單例對象的類方法。您可以將類方法命名爲任何東西,但通常的做法是將其稱爲sharedName或defaultName。

請檢查與最佳答案 鏈接:爲http://www.idev101.com/code/Objective-C/singletons.html