[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sayHello:) name:HelloWorldNotification object:nil];
これに従って、自前で作るシングルトンクラスもなんちゃらセンターと言う名前で作りがちです。僕の場合、
- SupportCenter
- ActivityCenter
- DownloadCenter
などなど。それぞれのクラスにクラスメソッドとしてsharedCenterというメソッドを定義して使ってます。こんな感じ。
[[SupportCenter sharedCenter] alertError:error];
このパターン、便利なんですがコードの中では結局グローバル変数を使って管理するという、まああまり見たくないコードでして、アナライザーに文句言われないためにもちゃんと終了時にグローバル変数を破棄してあげる必要があったり。簡単なことだけどちょっと面倒くさい。
というわけで、メタに考えました。シングルトンを管理するシングルトンクラス、SharedCenter。
SharedCenter.h
// // SharedCenter.h // Ramblin // // Created by Yosuke Suzuki on 10/03/27. // Copyright 2010 Kanshin, Inc.. All rights reserved. // #import <foundation/foundation.h> @interface SharedCenter : NSObject + (id)center:(Class)cls; + (void)registerCenter:(id)center forClass:(Class)cls; @end
SharedCenter.m
//
// SharedCenter.m
// Ramblin
//
// Created by Yosuke Suzuki on 10/03/27.
// Copyright 2010 Kanshin, Inc.. All rights reserved.
//
#import "SharedCenter.h"
@implementation SharedCenter
static NSMutableDictionary *sharedCenters = nil;
+ (void)initialize {
sharedCenters = [[NSMutableDictionary alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(closeCenters:) name:UIApplicationWillTerminateNotification object:nil];
}
+ (id)center:(Class)cls {
id center = nil;
@synchronized(sharedCenters) {
NSString *className = NSStringFromClass(cls);
center = [sharedCenters objectForKey:className];
if (!center) {
center = [[cls alloc] init];
[sharedCenters setObject:center forKey:className];
[center release];
}
}
return center;
}
+ (void)registerCenter:(id)center forClass:(Class)cls {
@synchronized(sharedCenters) {
[sharedCenters setObject:center forKey:NSStringFromClass(cls)];
}
}
+ (void)closeCenters:(NSNotification *)notification {
[sharedCenters release];
sharedCenters = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end
このクラスを使えば、どんなクラスでも簡単にシングルトンパターンが使えます。しかもグローバル変数は一つだけ。すっきりです。
SupportCenter.h
@interface SupportCenter : NSObject {
...
}
+ (SupportCenter *)sharedCenter; // 定義を追加
...
SupportCenter.m
#import "SupportCenter.m.h"
#import "SharedCenter.h"
@implementation ActivityCenter
// 実装を追加
+ (ActivityCenter *)sharedCenter {
return [SharedCenter center:[self class]];
}
...
