2012-02-28 7 views
1

で通知名のために観察すると、私はそうのように、特定の通知名を見て切り替えるためのメソッドを持つオブジェクトを持っています。しかし、同じ通知に応答する必要がある別の方法handleB:があります。NSNotificationCenterだから、複数の方法

- (void)startWatchingForB 
{ 
    [[NSNotificationCenter defaultCenter] addObserver: self 
              selector: @selector(handleB:) 
               name: SomeNotificationName 
               object: nil]; 
} 

- (void)stopWatchingForB 
{ 
    [[NSNotificationCenter defaultCenter] removeObserver: self 
                name: SomeNotificationName 
                object: nil]; 
} 

問題は、stopWatchingAまたはstopWatchingBが呼び出されるべきであるということである、オブジェクトは両方のために見て停止します。 1つの観測インスタンスを削除する方法はありますか?

stopWatchingForAを呼び出すと、handleA:が呼び出されないようにするのが理想的です。Bから完全に独立しています。

答えて

2

若干の再設計はどうですか?通知を受け取るメソッドは1つだけです。これで何をしたいのかを示す2つのフラグがあります。

@implementation ThisObject 
{ 
    BOOL isWatchingForA; 
    BOOL isWatchingForB; 
} 

- (void) registerForNotifications { 

    [[NSNotificationCenter defaultCenter] addObserver: self 
             selector: @selector(handleNotification:) 
              name: SomeNotificationName 
              object: nil]; 
} 

- (void) deregisterForNotifications { 
    if(!isWatchingA && !isWatchingB){ 
     [[NSNotificationCenter defaultCenter] removeObserver: self 
               name: SomeNotificationName 
               object: nil]; 
    } 
} 


- (void) startWatchingForA { 
    isWatchingForA = YES; 
} 
- (void) stopWatchingForA { 
    isWatchingForA = NO; 
} 

- (void) startWatchingForB { 
    isWatchingForB = YES; 
} 
- (void) stopWatchingForB { 
    isWatchingForB = NO; 
} 

- (void) handleNotification: (NSNotification *)note { 

    if(isWatchingForA){ 
     [self handleA:note]; 
    } 
    if(isWatchingB){ 
     [self handleB:note]; 
    } 
} 

//... 

@end 
+1

はい、[@ implementation'のivarsの宣言は正当です](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocDefiningClasses.html#//apple_ref/doc/uid/TP30001163-CH12-TPXREF126)をコンパイルしてください。 –

+0

さらに便利な機能の1つ! @private実装変数は多くの点で有用です。 –

+0

+1はよく考えられた答えです!私は受け入れますが、私が行った方法ではありません。私は私の答えで説明します。 –

1

ブロックとmikeashは、もう一度私の一日を節約しました。

私が最初の質問で省略したことの1つは、このパラダイムがカテゴリセーフであることです。これは、フラグとしてivarsまたはプロパティを意味しませんでした。 aBlockが実行される間、

#import <objc/runtime.h> 

static void *AHandlerKey; 
static void *BHandlerKey; 

- (void)startWatchingForA 
{ 
    // initialize `void (^aBlock)(NSNotification *)` block 
    id AHandler = [[NSNotificationCenter defaultCenter] addObserverForName: SomeNotificationName 
                    object: nil 
                    queue: nil 
                   usingBlock: aBlock]; 

    objc_setAssociatedObject(self, AHandlerKey, AHandler, OBC_ASSOCIATION_RETAIN); 
} 

- (void)stopWatchingForA 
{ 
    id AHandler = objc_getAssociatedObject(self, AHandlerKey); 
    [[NSNotificationCenter defaultCenter] removeObserver: AHandler 
                name: SomeNotificationName 
                object: nil]; 
} 

- (void)startWatchingForB 
{ 
    // initialize `void (^bBlock)(NSNotification *)` block 
    id BHandler = [[NSNotificationCenter defaultCenter] addObserverForName: SomeNotificationName 
                    object: nil 
                    queue: nil 
                   usingBlock: bBlock]; 

    objc_setAssociatedObject(self, BHandlerKey, BHandler, OBC_ASSOCIATION_RETAIN); 
} 

- (void)stopWatchingForB 
{ 
    id BHandler = objc_getAssociatedObject(self, BHandlerKey); 
    [[NSNotificationCenter defaultCenter] removeObserver: BHandler 
                name: SomeNotificationName 
                object: nil]; 
} 

この方法では、AHandlerが通知を受け、同様にBHandler/bBlock:ここで私がやってしまったものです。オブザーバとしてAHandlerを削除すると、BHandlerは影響を受けず、その逆もあります。完璧!

更新:オブジェクト結合の使用を提案したJosh Caswellに大きな感謝!

+0

非常に良い!私はあなたのソリューションがより好きです! (私はブロックベースの通知ルートに賛成するようになりました) –

+0

これで問題があります: 'static'変数は、このクラスの複数のインスタンスにわたって機能しません(異なるオブザーバオブジェクトが毎回返されると仮定します) 、 いずれかの方法)。あなたは、関連するオブジェクトの使用のビットをスローすることができます。 –

+0

素晴らしいアイデア。それが何かを知らなかった!やりますが、それに応じて更新します。 –

関連する問題