2012-04-11 200 views
3

我創建了一個單例類來跟蹤我的iPhone應用程序中的數據。我知道singleton只需要實例化一次,但是實例化它的最佳位置是什麼?這應該在appDelegate中完成嗎?我想能夠從多個類中調用這個單例(包含一個NSMutableArray),以便我可以訪問該數組。實例化單例類

這裏是我的課我寫道:

#import "WorkoutManager.h" 

static WorkoutManager *workoutManagerInstance; 

@implementation WorkoutManager 
@synthesize workouts; 

+(WorkoutManager*)sharedInstance { 
    if(!workoutManagerInstance) { 
     workoutManagerInstance = [[WorkoutManager alloc] init]; 
    } 
    return workoutManagerInstance; 
} 

-(id)init { 
    self = [super init]; 
    if (self) { 
     workouts = [[NSMutableArray alloc] init]; 
    } 
    return self; 
} 

@end 
+0

看看這個:http://stackoverflow.com/questions/145154/what-does-your-objective-c-singleton-look-like – 2012-04-11 00:46:12

+0

或這樣的:HTTP:// stackoverflow.com/questions/7568935/how-do-i-implement-an-objective-c-singleton-that-is-compatible-with-arc – 2012-04-11 00:47:03

+0

鏈接似乎是關於實施一個單身人士。我已經有了我的書面和運作。我在我的一個類中的一個IBAction中實例化它,但是我很困惑我是否應該在別處實例化它以便它是全局的? – TopChef 2012-04-11 00:49:17

回答

1

這可能是最簡單的方法:

static MyClass* theInstance = nil; 

+ (MyClass*) sharedInstance { 
    @synchronized(self) { 
     if (! theInstance) { 
      theInstance = [[MyClass alloc] init]; 
     } 
    } 

    return theInstance; 
} 

...所以在您要訪問的單身地方,你只是做[MyClass sharedInstance]以便獲得對該實例的參考。

請注意,這不會防止人們在您的單例類中手動調用allocinit來創建其他實例。如果您需要這樣做,您可以以類似於上述的方式實施init,以防止使用allocinit創建/返回其他實例。然而,在實踐中,單身人士課程最常使用sharedInstance方法(有時候在名稱上有微小的變化,如[UIApplication sharedApplication])。

+1

我推薦在http://stackoverflow.com/questions/7568935/how-do-i-implement-an-objective-c-singleton-that-is-compatible-with-arc回答中給出的GCD模式。 @synchronize解決方案的價格要高一些,而且自從添加dispatch_once以來,沒有理由支付這些費用。 – 2012-04-11 00:52:49

+0

兩種方法都可以,是的。我個人更喜歡'@ synchronized';我只是覺得它更具可讀性。 – aroth 2012-04-11 00:55:57

2

單身人士通常懶惰地實例化 - 第一次訪問時,實例被創建並從訪問方法返回。隨後對訪問方法的調用僅返回已創建的實例。

標準模式是:1.鎖定或以其他方式使以下線程安全(即dispatch_once())。 2.檢查單實例是否已經創建。 3.如果沒有,創建它。 4.釋放鎖定(如果適用)。 5.返回實例。

如果您因某種原因需要創建實例,則可能會出現這種情況。當類被添加到運行時時,運行時會發送類方法+load,該運行時在應用程序執行的早期階段。 (+initialize看起來也是一個候選人 - 它在運行時正好在類接收到它的第一個(其他)消息之前發送(不包括+load) - 但它實際上並沒有給你任何東西,因爲它會被髮送緊接在您發送sharedInstance之前。)

gcc __constructor__function attribute也可以工作(在clang中也是如此),儘管被記錄爲未針對ObjC實施。具有此屬性的函數將在輸入main()之前調用。不過,我不太確定這個選項的內存管理含義。運行時應該全部設置好,但是不會有autorelease池。

+0

這裏非常有用的技巧。 '+ load'是一個非常有用的工具,可以知道(儘管你經常不需要它)。 – 2012-04-11 00:54:12

0

通常單類實例化被訪問的第一次:

static SomeClass *_instance = nil; 

+ (SomeClass *) instance { 
    @synchronized(self) { 
     if (!_instance) 
      _instance = [[self alloc] init]; 
    } 
    return _instance; 
} 
0

我使用此代碼實例單身。GCD需要同步的護理

+ (SingletonClass *)sharedInstance { 
    static SingletonClass *sharedInstance; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
    sharedInstance = [[SingletonClass alloc] init]; 
    sharedInstance.property = [Property new]; 
    }); 
    return sharedInstance; 
}