Objective-C 中的單例

iOS 開(kāi)發(fā)中我最常用的設(shè)計(jì)模式就是單例模式 。用于在代碼間共享數(shù)據(jù),極為有效,不需要手動(dòng)傳遞數(shù)據(jù)。Cocoa Design Patterns 這本書寫的非常好,里面有很多有關(guān)單例模式和其它模式的內(nèi)容。


后端

單例類是需要重點(diǎn)理解的,它們展示出了一種非常實(shí)用的設(shè)計(jì)模式。整個(gè) iOS SDK 都使用了這個(gè)設(shè)計(jì)模式,例如 UIApplication 有一個(gè)方法叫做 sharedApplication,可以在任意地方調(diào)用,會(huì)返回一個(gè)與當(dāng)前運(yùn)行應(yīng)用相關(guān)的 UIApplication 實(shí)例。


如何實(shí)現(xiàn)

在 Objective-C 中,可以使用如下代碼實(shí)現(xiàn)一個(gè)單例類:

MyManager.h

#import <foundation/Foundation.h>

@interface MyManager : NSObject {
    NSString *someProperty;
}

@property (nonatomic, retain) NSString *someProperty;

+ (id)sharedManager;

@end

MyManager.m

#import "MyManager.h"

@implementation MyManager

@synthesize someProperty;

#pragma mark Singleton Methods

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

- (id)init {
  if (self = [super init]) {
      someProperty = [[NSString alloc] initWithString:@"Default Property Value"];
  }
  return self;
}

- (void)dealloc {
  // 應(yīng)該永遠(yuǎn)不會(huì)被調(diào)用,放在這里以表清晰。
}

@end

上面的代碼定義了一個(gè)叫做 sharedManager 的靜態(tài)變量(但只在此翻譯單元(translation unit)中是全局的),然后在 sharedManager 里初始化了一次,并且永遠(yuǎn)只有這一次初始化。怎么確保它只被創(chuàng)建一次呢?因?yàn)槭褂昧?GCD(Grand Central Dispatch)里面的 dispatch_once 方法。線程安全,完全由操作系統(tǒng)負(fù)責(zé),所以就不需要再多擔(dān)心什么了。

但如果你不想用 GCD,sharedManager 可以采用下面的代碼:

+ (id)sharedManager {
    static MyManager *sharedMyManager = nil;
    @synchronized(self) {
        if (sharedMyManager == nil)
            sharedMyManager = [[self alloc] init];
    }
    return sharedMyManager;
}

然后就可以在任意位置調(diào)用下面這個(gè)函數(shù)來(lái)引用單例了:

MyManager *sharedManager = [MyManager sharedManager];

我在項(xiàng)目中大量使用了這些代碼,例如創(chuàng)建一個(gè)單例來(lái)處理 CoreLocation 或 CoreData 函數(shù)。


無(wú) ARC 代碼

雖然我并不推薦這樣,但如果你沒(méi)有用 ARC(Automatic Reference Counting)的話,就應(yīng)該采用下面的代碼:

MyManager.h. 無(wú)ARC

#import "MyManager.h"

static MyManager *sharedMyManager = nil;

@implementation MyManager

@synthesize someProperty;

#pragma mark Singleton Methods
+ (id)sharedManager {
  @synchronized(self) {
      if(sharedMyManager == nil)
          sharedMyManager = [[super allocWithZone:NULL] init];
  }
  return sharedMyManager;
}
+ (id)allocWithZone:(NSZone *)zone {
  return [[self sharedManager] retain];
}
- (id)copyWithZone:(NSZone *)zone {
  return self;
}
- (id)retain {
  return self;
}
- (unsigned)retainCount {
  return UINT_MAX; //表示此對(duì)象無(wú)法被釋放
}
- (oneway void)release {
  // 永不釋放
}
- (id)autorelease {
  return self;
}
- (id)init {
  if (self = [super init]) {
      someProperty = [[NSString alloc] initWithString:@"Default Property Value"];
  }
  return self;
}
- (void)dealloc {
  // 應(yīng)該永遠(yuǎn)不會(huì)被調(diào)用,放在這里以表清晰。
  [someProperty release];
  [super dealloc];
}

@end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容