Objective-C NSNotificationCenter aracılığıyla mesaj göndermek ve almak?


610

NSNotificationCenterObjective-C ile mesaj gönderip almaya çalışıyorum . Ancak, bunun nasıl yapılacağına dair herhangi bir örnek bulamadım. Nasıl mesaj gönderip alırsınız NSNotificationCenter?


Gerçekten çok faydalı, teşekkürler. Bir şey, addObserver yöntemi, belirtilen seçiciden sonra sondaki noktalı virgül içermemelidir (en azından bu sürümümde bir istisnaya neden olmuştur). Yukarıdaki kodu düzenlemeyi denedim ancak orijinal koddaki biçimlendirme sorunları nedeniyle değişiklik kabul edilmedi.
Braunius


2
Bu q çok temel ve geniş, biraz googleing iyi
görünecekti

Bu, ilgili bir soruya çok benziyor: stackoverflow.com/questions/7896646/…
David Douglas

55
Stack Overflow kullanıcıları kullanışlılığını çok açık bir şekilde yorumladığında, böyle bir soruyu saçma buluyorum
Chet

Yanıtlar:


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

... başka bir sınıfta başka bir yerde ...

- (void) someMethod
{

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

}

2
Sadece [NSNotificationCenter defaultCenter] 'ın nereye yerleştirileceğini merak ediyor. AppDelegate'inize yerleştirmek en iyisidir?
Fulvio

14
@Fulvio: Başvurunuzun tüm bölümlerini etkileyebilecek bildirimler alıyorsanız veya gönderiyorsanız, AppDelegate'inize koyun. Yalnızca tek bir sınıfı etkileyen bildirimler alıyorsanız / yayınlıyorsanız, bu sınıfı o sınıfa koyun.
dreamlax

1
@dreamlax Truth, ancak dikkat çekmeye değer çünkü bu soru çoğunlukla bildirim dinleyicisini ihtiyaç duyduklarından daha uzun süre canlı tutan yeni ios devs tarafından aranıyor. Şimdi arc ile genellikle dealloc kullanmazsınız ve sonuç olarak bazıları dinleyiciyi serbest bırakmak zorunda olmadıklarını düşünebilir.
Vive

7
Ayrıca [super dealloc], dealloc yöntemindeki çağrıya ARC altında izin verilmediğini belirtmek gerekir ; gerisi iyi.
tommys

1
Bildirim tetiklenirse ve gözlemci yoksa ne olur? Bildirim kayboldu mu? Yoksa yeni bir gözlemciye (daha sonra yaratılacak) gönderilmeye hazır bir yerde “kurtarıldı” mı?
superpuccio

226

Dreamlax örneğini genişletmek için ... Bildirimle birlikte veri göndermek istiyorsanız

Posta kodunda:

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

Kodu gözlemlerken:

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

    NSDictionary *userInfo = notification.userInfo;
    MyObject *myObject = [userInfo objectForKey:@"someKey"];
}

TestNotification NSString türü olmalıdır. NSNotification örnek değişkeni mi?
RomanHouse

1
selfReceTestNotification yönteminde gözlemciye erişebilir miyim ?
neden

neden evet. ReceitTestNotification bir örnek yöntemidir ve örneğin kendisinden içindeki örneğe erişebilirsiniz.
Michael Peterson

Bu kadar. Alıcı yönteminden UserInfo almak için bir yol arıyordu.
hasan

Bütün bu gözlemci fikri tüm vakaları kapsamıyor gibi görünüyor. Bu uygulama ne zaman işe yaramadı. kapatıldı ve bildirim merkezinin bildirildiği bir bildirim formu. gözlemci yöntemi çağrılmaz.
hasan

49

Bu bana yardımcı oldu:

// 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"); 
}

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


Bu benim için çalıştı! Teşekkürler
Rakshitha Muranga Rodrigo

48

Ayrıca blok kullanma olasılığı vardır:

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

          // ...
     }];

Apple'ın belgeleri


1
Bu, şu anda oldukça eski olan cevabım için iyi bir güncelleme. Giriş veya ARC ve bloklar ile bildirim merkezlerinin üstesinden gelmek çok daha kolaydır.
dreamlax

5
Ben de öyle düşündüm, ama gerçek olamayacak kadar iyi olduğu ortaya çıktı. Bu durumda, addObserver'ın döndürdüğü gözlemciyi tutmanız ve daha sonra bunu kaldırmanız gerekir; bu, daha fazla değilse, yeni bir yöntem oluşturmak kadar karmaşık hale getirir. Daha fazla bilgi: toastmo.com/blog/2012/12/04/…
Andrew

42

görünümünüzü güncellemek için NSNotificationCenter kullanıyorsanız, şunu arayarak ana diziden göndermeyi unutmayın dispatch_async:

dispatch_async(dispatch_get_main_queue(),^{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"my_notification" object:nil];
});

1
ana iş parçacığından veya yalnızca görünümü gerçekten güncelleştirdiğinizde, yani ana iş parçacığına gönderdiğiniz bildirimi alan yöntemin içinde gerçekleşmesi gereken bildirim gönderisi mi?
Crashalot

1
bildirimi gönderdiğiniz iş parçacığı, işlevleri çalıştıran ve böylece kullanıcı arabirimini değiştirmeye çalışan iş parçacığıdır. aynen söylediğin gibi, fonksiyonların içindeki ana iş parçacığına gönderimi de kullanabilirsiniz: D. aynı sonuca sahip olmalı, perheps daha da iyi: D
eiran

1
@eiran, çok teşekkür ederim kardeşim, sadece dispatch_async içine yazdıktan sonra çalıştı
Arshad Shaik

2

Yeni başlayanlar için seçilen cevabın SWIFT 5.1'i

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!")
        }
    }
}

... başka bir sınıfta başka bir yerde ...

 func someMethod(){
        // All instances of TestClass will be notified
        NotificationCenter.default.post(name: "TestNotification", object: self)
 }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.