Как передать объект с помощью NSNotificationCenter

109

Я пытаюсь передать объект из моего делегата приложения в приемник уведомлений в другом классе.

Я хочу передать целое число messageTotal. Прямо сейчас у меня есть:

В приемнике:

- (void) receiveTestNotification:(NSNotification *) notification
{
    if ([[notification name] isEqualToString:@"TestNotification"])
        NSLog (@"Successfully received the test notification!");
}

- (void)viewDidLoad {
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dismissSheet) name:UIApplicationWillResignActiveNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveTestNotification:) name:@"eRXReceived" object:nil];

В классе, который выполняет уведомление:

[UIApplication sharedApplication].applicationIconBadgeNumber = messageTotal;
[[NSNotificationCenter defaultCenter] postNotificationName:@"eRXReceived" object:self];

Но я хочу передать объект messageTotal другому классу.

Теги:
cocoa-touch
nsnotificationcenter
nsnotifications

4 ответа

208
Лучший ответ

Вам придется использовать вариант "userInfo" и передать объект NSDictionary, содержащий целое число messageTotal:

NSDictionary* userInfo = @{@"total": @(messageTotal)};

NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc postNotificationName:@"eRXReceived" object:self userInfo:userInfo];

На получающей стороне вы можете получить доступ к словарю userInfo следующим образом:

-(void) receiveTestNotification:(NSNotification*)notification
{
    if ([notification.name isEqualToString:@"TestNotification"])
    {
        NSDictionary* userInfo = notification.userInfo;
        NSNumber* total = (NSNumber*)userInfo[@"total"];
        NSLog (@"Successfully received test notification! %i", total.intValue);
    }
}
  • 0
    Спасибо, я устанавливаю messageTotal для значка на UIButton, вы знаете, как я могу обновить кнопку с новым количеством значков? Код для отображения изображения в viewDidLoad : UIBarButtonItem *eRXButton = [BarButtonBadge barButtonWithImage:buttonImage badgeString:@"1" atRight:NO toTarget:self action:@selector(eRXButtonPressed)];
  • 2
    Это отдельный вопрос!
Показать ещё 2 комментария
76

Основываясь на предоставленном решении, я подумал, что было бы полезно показать пример, передающий свой собственный объект данных (который я назвал здесь как "сообщение" в соответствии с вопросом).

Класс A (отправитель):

YourDataObject *message = [[YourDataObject alloc] init];
// set your message properties
NSDictionary *dict = [NSDictionary dictionaryWithObject:message forKey:@"message"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"NotificationMessageEvent" object:nil userInfo:dict];

Класс B (приемник):

- (void)viewDidLoad
{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter]
     addObserver:self selector:@selector(triggerAction:) name:@"NotificationMessageEvent" object:nil];
}

#pragma mark - Notification
-(void) triggerAction:(NSNotification *) notification
{
    NSDictionary *dict = notification.userInfo;
    YourDataObject *message = [dict valueForKey:@"message"];
    if (message != nil) {
        // do stuff here with your message data
    }
}
  • 2
    почему этот ответ не имеет больше голосов ?! это работает отлично и не взломать!
  • 4
    @ Kairos, потому что он не предназначен для такого использования. параметр object в postNotificationName должен postNotificationName тот, который отправляет это уведомление.
Показать ещё 4 комментария
24

версия Swift 2

Как сказал @Johan Karlsson... Я делал это неправильно. Здесь правильный способ отправки и получения информации с помощью NSNotificationCenter.

Сначала мы рассмотрим инициализатор для postNotificationName:

init(name name: String,
   object object: AnyObject?,
 userInfo userInfo: [NSObject : AnyObject]?)

источник

Мы передадим нашу информацию с помощью параметра userInfo. Тип [NSObject : AnyObject] является удержанием от Objective-C. Итак, в Swift-стране все, что нам нужно сделать, это передать словарь Swift с ключами, которые получены из NSObject и значениями, которые могут быть AnyObject.

С помощью этого знания мы создаем словарь, который мы перейдем в параметр object:

 var userInfo = [String:String]()
 userInfo["UserName"] = "Dan"
 userInfo["Something"] = "Could be any object including a custom Type."

Затем мы передаем словарь в наш объектный параметр.

Sender

NSNotificationCenter.defaultCenter()
    .postNotificationName("myCustomId", object: nil, userInfo: userInfo)

Класс приемника

Сначала нам нужно убедиться, что наш класс наблюдает за уведомлением

override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("btnClicked:"), name: "myCustomId", object: nil)   
}

Затем мы можем получить наш словарь:

func btnClicked(notification: NSNotification) {
   let userInfo : [String:String!] = notification.userInfo as! [String:String!]
   let name = userInfo["UserName"]
   print(name)
}
  • 0
    Вы действительно нарушаете предполагаемое использование postNotificationName (). Но вы не одиноки. Я видел много разработчиков, использующих параметр объекта для отправки пользовательских объектов. Второй аргумент, объект, зарезервирован для отправителя. Вы действительно должны использовать userInfo для отправки всех видов объектов. В противном случае вы можете столкнуться со случайными сбоями и т. Д.
11

Swift 4

func post() {
    NotificationCenter.default.post(name: Notification.Name("SomeNotificationName"), 
        object: nil, 
        userInfo:["key0": "value", "key1": 1234])
}

func addObservers() {
    NotificationCenter.default.addObserver(self, 
        selector: #selector(someMethod), 
        name: Notification.Name("SomeNotificationName"), 
        object: nil)
}

@objc func someMethod(_ notification: Notification) {
    let info0 = notification.userInfo?["key0"]
    let info1 = notification.userInfo?["key1"]
}

Бонус (вам обязательно нужно!):

Замените Notification.Name("SomeNotificationName") на .someNotificationName:

extension Notification.Name {
    static let someNotificationName = Notification.Name("SomeNotificationName")
}

Замените "key0" и "key1" на Notification.Key.key0 и Notification.Key.key1:

extension Notification.Key {
    static let key0 = "key0"
    static let key1 = "key1"
}

Почему я должен это делать? Чтобы избежать дорогостоящих ошибок опечатки, наслаждайтесь переименованием, наслаждайтесь поиском и т.д....

Ещё вопросы

Сообщество Overcoder
Наверх
Меню