Senden und Empfangen von Nachrichten über NSNotificationCenter in Objective-C?

610

Ich versuche, Nachrichten NSNotificationCenterin Objective-C zu senden und zu empfangen . Ich konnte jedoch keine Beispiele dafür finden. Wie senden und empfangen Sie Nachrichten NSNotificationCenter?

hichris123
quelle
Wirklich sehr nützlich, danke. Eine Sache, die addObserver-Methode sollte nicht das abschließende Semikolon nach dem angegebenen Selektor haben (zumindest hat es in meiner Version eine Ausnahme verursacht). Ich habe versucht, den obigen Code zu bearbeiten, aber die Änderung wurde aufgrund von Formatierungsproblemen im Originalcode nicht akzeptiert.
Braunius
3
Das war großartig: cocoawithlove.com/2008/06/…
Aram Kocharyan
2
Dieses Q ist viel zu einfach und breit, ein wenig googeln wäre gut gewesen
Daij-Djan
Dies ist einer verwandten Frage hier sehr ähnlich: stackoverflow.com/questions/7896646/…
David Douglas
55
Ich finde es absurd, dass eine Frage wie diese geschlossen und nicht konstruktiv ist, wenn die Benutzer von Stack Overflow ihre Nützlichkeit so deutlich kommentiert haben
Chet

Antworten:

1019
@implementation TestClass

- (void) dealloc
{
    // If you don't remove yourself as an observer, the Notification Center
    // will continue to try and send notification objects to the deallocated
    // object.
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super dealloc];
}

- (id) init
{
    self = [super init];
    if (!self) return nil;

    // Add this instance of TestClass as an observer of the TestNotification.
    // We tell the notification center to inform us of "TestNotification"
    // notifications using the receiveTestNotification: selector. By
    // specifying object:nil, we tell the notification center that we are not
    // interested in who posted the notification. If you provided an actual
    // object rather than nil, the notification center will only notify you
    // when the notification was posted by that particular object.

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

    return self;
}

- (void) receiveTestNotification:(NSNotification *) notification
{
    // [notification name] should always be @"TestNotification"
    // unless you use this method for observation of other notifications
    // as well.

    if ([[notification name] isEqualToString:@"TestNotification"])
        NSLog (@"Successfully received the test notification!");
}

@end

... woanders in einer anderen Klasse ...

- (void) someMethod
{

    // All instances of TestClass will be notified
    [[NSNotificationCenter defaultCenter] 
        postNotificationName:@"TestNotification" 
        object:self];

}
Dreamlax
quelle
2
Ich frage mich nur, wo [NSNotificationCenter defaultCenter] platziert werden soll. Ist es am besten, es in Ihrem AppDelegate zu platzieren?
Fulvio
14
@Fulvio: Es hängt davon ab, ob Sie Benachrichtigungen erhalten oder veröffentlichen, die möglicherweise alle Teile Ihrer Anwendung betreffen, und diese in Ihr AppDelegate einfügen. Wenn Sie Benachrichtigungen erhalten / veröffentlichen, die nur eine einzelne Klasse betreffen, fügen Sie sie stattdessen in diese Klasse ein.
Dreamlax
1
@dreamlax Truth, es ist jedoch erwähnenswert, da diese Frage hauptsächlich von neuen iOS-Entwicklern gesucht wird, die den Benachrichtigungs-Listener länger am Leben halten, als sie benötigen. Jetzt verwenden Sie mit arc normalerweise kein Dealloc und daher denken einige möglicherweise, dass sie den Listener nicht freigeben müssen.
Vive
7
Es könnte auch erwähnenswert sein, dass der [super dealloc]Aufruf in der Dealloc-Methode unter ARC nicht zulässig ist; der Rest ist alles gut.
Tommy
1
Was passiert, wenn die Benachrichtigung ausgelöst wird und keine Beobachter anwesend sind? Geht die Benachrichtigung verloren? Oder ist es irgendwo "gespeichert", um an einen neuen Beobachter versendet zu werden (später erstellt)?
Superpuccio
226

Um das Beispiel von dreamlax zu erweitern ... Wenn Sie Daten zusammen mit der Benachrichtigung senden möchten

Im Buchungscode:

NSDictionary *userInfo = 
[NSDictionary dictionaryWithObject:myObject forKey:@"someKey"];
[[NSNotificationCenter defaultCenter] postNotificationName: 
                       @"TestNotification" object:nil userInfo:userInfo];

Bei der Beobachtung des Codes:

- (void) receiveTestNotification:(NSNotification *) notification {

    NSDictionary *userInfo = notification.userInfo;
    MyObject *myObject = [userInfo objectForKey:@"someKey"];
}
Michael Peterson
quelle
TestNotification muss vom Typ NSString sein. Ist es eine Instanzvariable NSNotification?
RomanHouse
1
Kann ich mit der selfMethode "receiveTestNotification" auf den Beobachter zugreifen?
Warum
Warum ja. receiveTestNotification ist eine Instanzmethode, auf die Sie über self in der Instanz selbst zugreifen können.
Michael Peterson
Das ist es. Ich suchte nach einer Möglichkeit, UserInfo von der Empfängermethode abzurufen.
Hasan
Es scheint, dass all diese Beobachteridee nicht alle Fälle abdeckt. Das hat bei der App nicht funktioniert. wurde geschlossen und ein Benachrichtigungsformular des Benachrichtigungszentrums wurde abgehört. Die Beobachtermethode wird nicht aufgerufen.
Hasan
49

Dieser hat mir geholfen:

// Add an observer that will respond to loginComplete
[[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(showMainMenu:) 
                                                 name:@"loginComplete" object:nil];


// Post a notification to loginComplete
[[NSNotificationCenter defaultCenter] postNotificationName:@"loginComplete" object:nil];


// the function specified in the same class where we defined the addObserver
- (void)showMainMenu:(NSNotification *)note {
    NSLog(@"Received Notification - Someone seems to have logged in"); 
}

Quelle: http://www.smipple.net/snippet/Sounden/Simple%20NSNotificationCenter%20example

j7nn7k
quelle
Das hat bei mir funktioniert! Danke
Rakshitha Muranga Rodrigo
48

Es besteht auch die Möglichkeit, Blöcke zu verwenden:

NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[[NSNotificationCenter defaultCenter] 
     addObserverForName:@"notificationName" 
     object:nil
     queue:mainQueue
     usingBlock:^(NSNotification *notification)
     {
          NSLog(@"Notification received!");
          NSDictionary *userInfo = notification.userInfo;

          // ...
     }];

Apples Dokumentation

Xavi Gil
quelle
1
Dies ist ein gutes Update meiner Antwort, das jetzt ziemlich veraltet ist. Mit der Einführung oder ARC und Blöcken sind Benachrichtigungszentren viel einfacher zu handhaben.
Dreamlax
5
Das habe ich auch gedacht, aber es stellt sich heraus, dass es zu schön ist, um wahr zu sein. In diesem Fall müssen Sie den Beobachter, den addObserver zurückgibt, beibehalten und später entfernen, was es genauso kompliziert macht wie das Erstellen einer neuen Methode, wenn nicht noch komplizierter. Weitere Informationen: toastmo.com/blog/2012/12/04/…
Andrew
42

Wenn Sie NSNotificationCenter zum Aktualisieren Ihrer Ansicht verwenden, vergessen Sie nicht, sie vom Hauptthread aus zu senden, indem Sie Folgendes aufrufen dispatch_async:

dispatch_async(dispatch_get_main_queue(),^{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"my_notification" object:nil];
});
Eiran
quelle
1
Ist es der Benachrichtigungsbeitrag, der vom Hauptthread aus erfolgen muss, oder nur, wenn Sie die Ansicht tatsächlich aktualisieren, dh innerhalb der Methode, die die Benachrichtigung empfängt, die Sie an den Hauptthread senden?
Crashalot
1
Der Thread, von dem Sie die Benachrichtigung senden, ist der Thread, in dem die Funktionen ausgeführt werden und der versucht, die Benutzeroberfläche zu ändern. Sie können auch den Versand an den Haupt-Thread innerhalb der Funktionen verwenden, genau wie Sie gesagt haben: D. sollte das gleiche Ergebnis haben, Perheps ist es noch besser: D
Eiran
1
@ Eiran, vielen Dank, Bruder, es hat erst funktioniert, nachdem ich in dispatch_async
Arshad Shaik geschrieben habe.
2

SWIFT 5.1 der ausgewählten Antwort für Neulinge

class TestClass {
    deinit {
        // If you don't remove yourself as an observer, the Notification Center
        // will continue to try and send notification objects to the deallocated
        // object.
        NotificationCenter.default.removeObserver(self)
    }

    init() {
        super.init()

        // Add this instance of TestClass as an observer of the TestNotification.
        // We tell the notification center to inform us of "TestNotification"
        // notifications using the receiveTestNotification: selector. By
        // specifying object:nil, we tell the notification center that we are not
        // interested in who posted the notification. If you provided an actual
        // object rather than nil, the notification center will only notify you
        // when the notification was posted by that particular object.

        NotificationCenter.default.addObserver(self, selector: #selector(receiveTest(_:)), name: NSNotification.Name("TestNotification"), object: nil)
    }

    @objc func receiveTest(_ notification: Notification?) {
        // [notification name] should always be @"TestNotification"
        // unless you use this method for observation of other notifications
        // as well.

        if notification?.name.isEqual(toString: "TestNotification") != nil {
            print("Successfully received the test notification!")
        }
    }
}

... woanders in einer anderen Klasse ...

 func someMethod(){
        // All instances of TestClass will be notified
        NotificationCenter.default.post(name: "TestNotification", object: self)
 }
Maneesh M.
quelle