Вопрос по objective-c, cocoa, nsnotificationcenter – NSNotificationCenter: список наблюдателей?

23

Можно ли получить список наблюдателей (объектов и селекторов) для данного имени уведомления? (NSNotificationCenter)

Это должно помочь вам -stackoverflow.com/questions/10346700/… Zayin Krige
Пожалуйста, попробуйте решение по 0xced (& lt;stackoverflow.com/users/21698/0xced>) & lt;stackoverflow.com/a/13274854/505735& GT; & Quot; Muhammad Usman Aleem

Ваш Ответ

6   ответов
1

Вместо использования NSNotificationCenter, вы можете попробовать этоObserversCenter, И вы можете получить список наблюдателей.

Об ObserverCenter:

it implements an multi-observer pattern as NSNotificationCenter; it decouple the observed and observers, so they don't know each other; you can subscribe on a specified key; you can call the real interface when making a notification.
-1

observationInfo собственность NSObject?

observationInfo
Returns a pointer that identifies information about all of the observers that are registered with the receiver.
Я думаю, это не для наблюдателей NSNotificationCenter, а для наблюдений ключ / значение.
Возможно, ты прав. Я не пробовал это с NSNotificationCenter
11

(iOS 9, Swift 3) Если вы хотите узнать, какие наблюдатели в настоящее время зарегистрированы вNotificationCenterсломайте и распечатайте описание отладки:

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

Каждая строка вывода будет содержать(Notification) Name, Object, Observer, Options, Несколько звонков наNotificationCenter.default.addObserver с некоторымиNSNotification.Name приведет к нескольким записям в этом списке.

NB. хотя это может оказаться полезной информацией при отладке, я бы не советовал управлять наблюдателями во время выполнения, используя этот вывод.

(источник:ответ основанный наuseyourloaf)

(lldb) e [NSNotificationCenter defaultCenter].debugDescription работает для obj-c.
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
14

Я не думаю, что есть (официальный) способ получения списка наблюдателей для данного имени уведомления из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 (очень к сожалению) полезно только в том случае, если вы используете сборщик мусора.
4

Нет открытого API для запросаNSNotificationCenter о списке текущих наблюдателей для любого объекта или уведомления.

Предыдущий ответ обрисовывает в общих чертах решение и идет к некоторому уровню детализации относительно собственности наблюдателей, в подклассеNSNotificationCenter предназначен для сбора и предоставления такой информации.

Однако это решение может использоваться только с вашим собственным кодом, который вызовет подклассNSNotiicationCenter, А как насчет другого кода, как в системной, так и во внешних библиотеках, которые используют базуNSNotificationCenter для регистрации / отмены регистрации для уведомлений?

Я предлагаю вместо подклассовNSNotificationCenter, используя немного низкоуровневого ObjC для реализации методов оригинальныхNSNotifictionCenterзаменяя их нашими собственными реализациями, которые будут работать более или менее, как описано в предыдущем ответе, и будут вызывать исходные реализации как их последний акт.

Вот как это сделать:http://nshipster.com/method-swizzling/

Затем вы можете быть уверены, что получите ВСЕХ наблюдателей какого-то уведомления, и что ваш код переносим и может использоваться с кодом третьей стороны, который напрямую используетNSNotificationCenter.

Похожие вопросы