デザインパターンのことを深く書きたいわけではありません。すいません。
- Singletonを使いたい
- delegateプロパティも便利なのでSingletonクラスに実装したい
というような状況でのちょっとしたTipsです。(もっとも最近はdelegateプロパティよりもBlock関数を使う方がお気に入りです。)
Delegateを実装したい場合、iOSでは下記のように記述するのが一般的と思いますが、
@property(nonatomic, weak) id <MyClassDelegate> delegate;
これでは、delegate変数の実体は一つだけなので、シングルトンオブジェクトのように複数のオブジェクトから処理を委譲されるクラスでは、このプロパティを使うことはできません。もちろんsetDelegateを書けば問題ないのですが、その中身は以下のようになるかと思います。
作戦は簡単で、delegateを沢山もつ、すなわちNSMutableArrayに放り込むということです。
これによって複数のオブジェクトから扱うできます。
(※このような実装をするとデザインパターン的にはobserverパターンであるとのご指摘をいただきました。)
委譲したオブジェクトは、自分がdeallocされるときに必ず
removeDelegateを忘れないようにしましょう。
まずdelegateを格納するNSMutableArrayを宣言します。このインターフェイス記述はヘッダー用ではなくてMyClass.mの方に記述します。(細かいことですが外部にプライベートな変数を公開しないで済むObjective-Cは素晴らしいと思います)
@interface MyClass ()
{
NSMutableArray * mDelegates;
}
@end
実装部では、add/remove/doの3つのメソッドを書くだけです。
/**
* 複数のdelegateを保持する
*/
- (void)addDelegate:(id <MyClassDelegate> )delegate
{
if(mDelegates == nil)
{
mDelegates = [[NSMutableArray alloc] init];
}
[mDelegates addObject:delegate];
}
/**
* 保持したデリゲートを削除する
*/
- (void)removeDelegate:(id <MyClassDelegate> )delegate
{
[mDelegates removeObject:delegate];
}
/**
* デリゲートを実行する。
*/
- (void)doDelegate:(NSInteger)completeType
{
dispatch_async(dispatch_get_main_queue(), ^{
[mDelegates enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL * stop) {
id delegate = obj;
if((delegate != nil) &&
[delegate respondsToSelector:@selector(MyClass:updateCompleted:)])
{
[delegate MyClass:self updateCompleted:completeType];
}
}];
});
}
要するに
[[NSNotificationCenter defaultCenter] addObserver:self
これと同様の実装しましょう、ということになると思います。
メソッド名もaddObserverに変えたほうが良いかも・・・