有没有可能获取给定通知名称的观察者列表(对象和选择器)?(NSNotificationCenter)
有没有可能获取给定通知名称的观察者列表(对象和选择器)?(NSNotificationCenter)
(iOS 9,Swift 3) 如果您想查找当前在NotificationCenter
中注册的观察者,请打断并打印其调试描述:
(iOS 9,Swift 3) 如果您想查找当前在NotificationCenter
中注册的观察者,请打断并打印其调试描述:
(lldb) e print(NotificationCenter.default.debugDescription)
每一行输出都将包含(通知)名称,对象,观察者,选项。使用一些NSNotification.Name
多次调用NotificationCenter.default.addObserver
将在此列表中生成多个条目。
(lldb) e [NSNotificationCenter defaultCenter].debugDescription
对于 obj-c 可以工作。 - rstackhouse我认为没有(官方的)方法可以从 NSNotificationCenter
中检索给定通知名称的观察者列表。但是,您可以创建 NSNotificationCenter
的子类,然后覆盖以下方法:
+ defaultCenter
- addObserver:selector:name:object
- addObserverForName:object:queue:usingBlock:
- removeObserver:
- removeObserver:name:object
在这些实例方法的重写实现中,您可以使用字典跟踪给定通知名称的观察者。在每个重写的实例方法中,最后调用 NSNotificationCenter
相应的 super
方法。此外,您还将提供一个方法来检索给定名称的观察者列表,例如:
- (id)observerForNotificationName:(NSString *)name
然而,该方法存在两个问题:首先,在一个简单的实现中,NSMutableDictionary
会保留所有的观察者,这可能不是 NSNotificationCenter
实现的相同行为。其次,您需要更改获取默认通知中心的代码,即使用自定义子类替换 [NSNotificationCenter defaultCenter]
(或任何其他 NSNotificationCenter
实例)。CFDictionary
、带有对应观察者的弱引用的 容器类,或者在 Mac OS X 的垃圾回收环境中使用 NSHashTable
来解决。NSHashTable
只有在使用垃圾回收(Garbage Collection)时才有用处,这非常不幸。 - Rob Keniger NSNotificationCenter 的子类中拥有观察者所有权的问题,该子类旨在收集和提供这些信息。然而,这种解决方案只能用于您自己的代码,即将调用 NSNotiicationCenter
的子类。那么其他代码呢?无论是系统中的还是使用基本 NSNotificationCenter 进行注册/注销通知的外部库?
我建议不要使用 NSNotificationCenter 的子类,而是使用一些低级别的ObjC来控制原始 NSNotifictionCenter 的方法实现,用我们自己的实现替换它们。这些实现将更多或少地按照先前答案中描述的方式工作,并将最后调用原始实现。
以下是如何完成此操作:http://nshipster.com/method-swizzling/
然后,您可以确保获取某个通知的所有观察者,并且您的代码是可移植的,并可与直接使用 NSNotificationCenter 的第三方代码一起使用。
我在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
不要使用NSNotificationCenter,你可以尝试使用ObserversCenter。你可以获得观察者列表。
关于ObserverCenter:
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
这适用于Xcode 12,在旧版本中,可能需要使用debugDescription
。
observationInfo
属性吗?observationInfo
Returns a pointer that identifies information about all of the observers that are registered with the receiver.