35

特定の通知名のオブザーバー(オブジェクトとセレクター)のリストを取得することは可能ですか?(NSNotificationCenter)

4

7 に答える 7

27

(iOS 9、Swift 3)現在登録されているオブザーバーを確認したい場合はNotificationCenter、デバッグの説明を中断して印刷します。

(lldb) e print(NotificationCenter.default.debugDescription)

出力の各行には、(通知)NameObjectObserverOptionsが含まれます。を複数回呼び出すとNotificationCenter.default.addObserverNSNotification.Nameこのリストに複数のエントリが作成されます。


NB。これはデバッグ時に役立つ情報になる可能性がありますが、この出力を使用して実行時にオブザーバーを管理することはお勧めしません。


(出典:useyourloafに基づく回答

于 2017-05-14T14:30:38.073 に答える
15

から特定の通知名のオブザーバーのリストを取得する(公式の)方法はないと思いますNSNotificationCenter。ただし、のサブクラスを作成してからNSNotificationCenter、次のメソッドをオーバーライドすることができます。

  • + defaultCenter
  • - addObserver:selector:name:object
  • - addObserverForName:object:queue:usingBlock:
  • - removeObserver:
  • - removeObserver:name:object

インスタンスメソッドのオーバーライド実装では、ディクショナリを使用して、特定の通知名のオブザーバーを追跡します。オーバーライドされた各インスタンスメソッドで、最終的にNSNotificationCenterのそれぞれのsuperメソッドを呼び出します。さらに、指定された名前のオブザーバーの独自のリストを取得するメソッドを提供します。次に例を示します。

- (id)observerForNotificationName:(NSString *)name

ただし、このアプローチには2つの問題があります。1つは、NSMutableDictionaryすべてのオブザーバーを単純な実装に保持することです。これは、おそらく同じ動作のNSNotificationCenter実装ではありません。次に、カスタムサブクラスを使用するために、デフォルトの通知センターを取得するコード[NSNotificationCenter defaultCenter](またはその他のインスタンス)を変更する必要があります。NSNotificationCenter

CFDictionary最初の問題は、弱参照コールバック、それぞれのオブザーバーへの弱参照を持つコンテナクラス、またはMac OS Xのガベージコレクション環境にいる場合は、を使用して解決できることに注意してくださいNSHashTable

于 2012-04-27T07:54:58.877 に答える
5

NSNotificationCenterオブジェクトまたは通知の現在のオブザーバーのリストについて照会するためのパブリックAPIはありません。

NSNotificationCenter前の回答は、解決策の概要を示し、そのような情報を収集して提供するように設計されたサブクラスで、オブザーバーの所有権に関するある程度の詳細に行きます。

ただし、このソリューションは、のサブクラスを呼び出す独自のコードでのみ使用できますNSNotiicationCenterNSNotificationCenter通知の登録/登録解除にベースを使用するシステムライブラリと外部ライブラリの両方の他のコードはどうですか?

サブクラス化する代わりにNSNotificationCenter、少し低レベルのObjCを使用して、元のメソッド実装をスウィズルし、NSNotifictionCenterそれらを独自の実装に置き換えることをお勧めします。これは、前の回答で説明したように多かれ少なかれ機能し、元の実装を呼び出します。彼らの最後の行為として。

これを行う方法は次のとおりです:http://nshipster.com/method-swizzling/

次に、通知のすべてのオブザーバーを確実に取得し、コードが移植可能であり、を直接使用するサードパーティのコードで使用できることを確認できますNSNotificationCenter

于 2014-10-21T13:15:09.477 に答える
1

NSNotificationCenterを使用する代わりに、このObserversCenterを試すことができます。そして、オブザーバーのリストを取得できます。

ObserverCenterについて:

  1. NSNotificationCenterとしてマルチオブザーバーパターンを実装します。
  2. それは観察者と観察者を切り離すので、彼らはお互いを知りません。
  3. 指定したキーでサブスクライブできます。
  4. 通知を行うときに実際のインターフェースを呼び出すことができます。
于 2015-03-03T05:53:21.170 に答える
1

NSNotificationCenterでカテゴリを作成し、addObserver::::メソッドをスウィズリングしました。

これはデバッグ専用であり、保持サイクルにつながるため、本番コードに含めることはできません。

@interface NSNotificationCenter (Tracking)
@property (nonatomic) NSMutableArray <NSDictionary *> * observers;
@end


#import <JRSwizzle/JRSwizzle.h>
@implementation NSNotificationCenter (Tracking)

+ (void)initialize {
    [super initialize];
    [self jr_swizzleMethod:@selector(addObserver:selector:name:object:)
                withMethod:@selector(SNaddObserver:selector:name:object:)
                     error:nil];
}

- (void)SNaddObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject {
    NSDictionary *obs = @{@"observer"   :observer,
                          @"selector"   :NSStringFromSelector(aSelector),
                          @"name"       :aName
                          };
    DDLogDebug(@"observer added : %@", obs);
    [[self observers] addObject:obs];
    [self SNaddObserver:observer selector:aSelector name:aName object:anObject];
}

- (NSMutableArray <NSDictionary *> *) observers{
    static NSMutableArray <NSDictionary *> * _observers = nil;
    if (!_observers) {
        _observers = [NSMutableArray new];
    }
    return _observers;
}

@end
于 2016-01-09T11:11:02.757 に答える
1

@PDKの回答と同様に、po NotificationCenter.default(または適切なインスタンス)はデバッグ情報を生成します。

<NSNotificationCenter:0x600000f84310>
Name, Object, Observer, Options
UIApplicationSimpleRemoteActionNotification, 0x7faac90069a0, 0x600000f84fc0, 1400
NSTextStorageDidProcessEditingNotification, 0x7faacd80d080, 0x600001808a00, 1400
com.apple.ManagedConfiguration.profileListChanged, 0x600000b0e280, 0x600000b0e280, 1400
UIApplicationDidBecomeActiveNotification, 0x7faac90069a0, 0x600000ff75d0, 1400
UIApplicationDidBecomeActiveNotification, 0x7faac90069a0, 0x600001880d00, 1400

これはXcode12で機能し、古いバージョンではdebugDescription必要になる場合があります。

于 2020-12-10T14:55:03.913 に答える
-2

observationInfoNSObjectのプロパティを試しましたか?

observationInfo
Returns a pointer that identifies information about all of the observers that are registered with the receiver.
于 2014-11-14T07:13:07.773 に答える