web-dev-qa-db-fra.com

Comment passer un objet avec NSNotificationCenter

J'essaie de transmettre un objet de mon délégué d'application à un récepteur de notification d'une autre classe.

Je veux passer un entier messageTotal. En ce moment j'ai:

En récepteur:

- (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];

Dans la classe qui fait la notification:

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

Mais je veux passer l'objet messageTotal à l'autre classe.

121
Jon

Vous devrez utiliser la variante "userInfo" et transmettre un objet NSDictionary contenant l'entier messageTotal:

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

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

Sur le destinataire, vous pouvez accéder au dictionnaire userInfo comme suit:

-(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);
    }
}
225
LearnCocos2D

En me basant sur la solution fournie, j'ai pensé qu'il pourrait être utile de montrer un exemple en passant votre propre objet de données personnalisé (que j'ai référencé ici en tant que "message" selon la question).

Classe A (expéditeur):

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

Classe B (récepteur):

- (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
    }
}
89
David Douglas

Swift 2 Version

Comme @Johan Karlsson l'a fait remarquer… je me trompais. Voici le moyen approprié d'envoyer et de recevoir des informations avec NSNotificationCenter.

Premièrement, examinons l’initialiseur de postNotificationName:

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

source

Nous transmettrons nos informations à l'aide du paramètre userInfo. Le [NSObject : AnyObject] type est un report de Objective-C. Donc, dans Swift land, tout ce que nous avons à faire est de passer un Swift dictionnaire qui contient des clés dérivées de NSObject et des valeurs qui peut être AnyObject.

Forts de cette connaissance, nous créons un dictionnaire que nous passerons dans le paramètre object:

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

Ensuite, nous passons le dictionnaire dans notre paramètre d'objet.

Expéditeur

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

Classe de réception

Nous devons d’abord nous assurer que notre classe observe la notification

override func viewDidLoad() {
    super.viewDidLoad()

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

Ensuite, nous pouvons recevoir notre dictionnaire:

func btnClicked(notification: NSNotification) {
   let userInfo : [String:String!] = notification.userInfo as! [String:String!]
   let name = userInfo["UserName"]
   print(name)
}
24
Dan Beaulieu

Swift 5

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"]
}

Bonus (que vous devez absolument faire!):

Remplacez Notification.Name("SomeNotificationName") par .someNotificationName:

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

Remplacez "key0" Et "key1" Par Notification.Key.key0 Et Notification.Key.key1:

extension Notification {
  enum Key: String {
    case key0
    case key1
  }
}

Pourquoi devrais-je définitivement faire ça? Pour éviter les erreurs de frappe coûteuses, renommez, retrouvez les utilisations, etc.

17
frouo