Objective-Cでシングルトンを作る方法

MRCの場合とARCの場合で異なるようだ。

MRCの場合

Objective-Cで自分の作ったクラスでシングルトンな動作をさせようと思ったら、公式ドキュメントを見るのが一番早かった。

http://developer.apple.com/jp/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/chapter_3_section_10.html

以下、上記サイトから引用して一部改変。

static MyGizmoClass *sharedGizmoManager = nil;

+ (MyGizmoClass*)sharedManager {
	@synchronized(self) {
		if (sharedGizmoManager == nil) {
			[[self alloc] init]; // ここでは代入していない
		}
	}
	return sharedGizmoManager;
}

+ (id)allocWithZone:(NSZone *)zone {
	@synchronized(self) {
		if (sharedGizmoManager == nil) {
			sharedGizmoManager = [super allocWithZone:zone];
			return sharedGizmoManager;  // 最初の割り当てで代入し、返す
		}
	}
	return nil; // 以降の割り当てではnilを返すようにする
}

- (id)copyWithZone:(NSZone *)zone {
    return self;
}

- (id)retain {
    return self;
}

- (unsigned)retainCount {
	return UINT_MAX;  // 解放できないオブジェクトであることを示す
}

- (void)release {
    // 何もしない
}

- (id)autorelease {
	return self;
}

以上。

ARCの場合

2013年11月28日追記

Stack OverflowのWhy does Apple recommend to use dispatch_once for implementing the singleton pattern under ARC?という記事によれば、AppleはSingletonパターンを使う時にdispatch_onceの使用を勧めているという。たしかに、Grand Central Dispatch(GCD)のドキュメントにシングルトンの初期化に便利と書いてあった。記事の通り、ARCのコードでは以下のように書くのがベターなようだ。以下引用。

+ (MyClass *)sharedInstance
{
    //  Static local predicate must be initialized to 0
    static MyClass *sharedInstance = nil;
    static dispatch_once_t onceToken = 0;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[MyClass alloc] init];
        // Do any other initialization stuff here
    });
    return sharedInstance;
}
Pocket
LINEで送る
LinkedIn にシェア