0

I am using NSNotificationCenter to send local notifications in my code and working in both Objective-C and Swift. I'm posting notifications from Objective-C And receiving in Swift. But the methods that I added in notification getting called multiple times and added observer only in viewDidLoad method.

Swift:

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.serverCardSynced), name: NSNotification.Name(rawValue: NOTIF_SERVER_CARD_SYNCED), object: nil);
    NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.checkForAutoSync), name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil);
    NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.initateSync), name: NSNotification.Name(rawValue: NOTIF_CONTACT_ENTITY_CHANGE), object:nil);
    NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.menuRemoved), name: NSNotification.Name(rawValue: NOTIF_MENU_REMOVED), object:nil);
    NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.reloadAllCards(_:)), name: NSNotification.Name(rawValue: NOTIF_RELOAD_ALL_CARDS), object:nil);
    NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.initateDownloadMyCards), name: NSNotification.Name(rawValue: NOTIF_DOWNLOAD_CARD), object:nil);
}

Objective-C:

- (void)applicationDidBecomeActive:(UIApplication *)application {
    self.isSyncPending = true;
    [[NSNotificationCenter defaultCenter] 
    postNotificationName:NOTIF_CONTACT_ENTITY_CHANGE object:nil];
}

-(void)insertData(){
    [[NSNotificationCenter defaultCenter] 
    postNotificationName:NOTIF_SERVER_CARD_SYNCED object:nil];
}

I added remove observer in my deinit but it is not even calling. How to stop calling multiple times.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
iVJ
  • 61
  • 1
  • 1
  • 13

3 Answers3

0
//call this method in viewDidLoad
fileprivate func registerNotifs() {

    //remove observer before adding to make sure that it is added only once

    NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NOTIF_SERVER_CARD_SYNCED), object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NOTIF_CONTACT_ENTITY_CHANGE), object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NOTIF_MENU_REMOVED), object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NOTIF_RELOAD_ALL_CARDS), object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: NOTIF_DOWNLOAD_CARD), object: nil)

    NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.serverCardSynced), name: NSNotification.Name(rawValue: NOTIF_SERVER_CARD_SYNCED), object: nil);
    NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.checkForAutoSync), name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil);
    NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.initateSync), name: NSNotification.Name(rawValue: NOTIF_CONTACT_ENTITY_CHANGE), object:nil);
    NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.menuRemoved), name: NSNotification.Name(rawValue: NOTIF_MENU_REMOVED), object:nil);
    NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.reloadAllCards(_:)), name: NSNotification.Name(rawValue: NOTIF_RELOAD_ALL_CARDS), object:nil);
    NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.initateDownloadMyCards), name: NSNotification.Name(rawValue: NOTIF_DOWNLOAD_CARD), object:nil);
}
Mahendra
  • 8,448
  • 3
  • 33
  • 56
0

you can do like this

fileprivate func registerLocalNotifications() {

    NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.serverCardSynced), name: NSNotification.Name(rawValue: NOTIF_SERVER_CARD_SYNCED), object: nil)
    NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.checkForAutoSync), name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil)
    NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.initateSync), name: NSNotification.Name(rawValue: NOTIF_CONTACT_ENTITY_CHANGE), object:nil)
    NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.menuRemoved), name: NSNotification.Name(rawValue: NOTIF_MENU_REMOVED), object:nil)
    NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.reloadAllCards(_:)), name: NSNotification.Name(rawValue: NOTIF_RELOAD_ALL_CARDS), object:nil)
    NotificationCenter.default.addObserver(self, selector:#selector(MainScreen.initateDownloadMyCards), name: NSNotification.Name(rawValue: NOTIF_DOWNLOAD_CARD), object:nil)
}

add above method in viewDidLoad and in

deinit {
        NotificationCenter.default.removeObserver(self)
}

REF : Where to remove observer for NSNotification in Swift?

Update:

Check you class instance if it already persist i.e in view when you are instantiating this view controller you can do like this

if let vc = yourNotificationViewCointrollerObj {
    // USE EXISTING ONE
} else {
    // CREATE NEW INSTANCE
}
Abhishek Thapliyal
  • 3,497
  • 6
  • 30
  • 69
0

NSNotificationCenter is a "publish-subscribe" mechanism where each posted notification is delivered to all subscribers (called observers). If you receive a notification multiple times it means that either you have multiple subscribers, or you are sending a notification multiple times.

I assume that you have only one subscriber for each notification type - your MainScreen UIViewController in Swift. It means that you probably send each notification multiple times.

For example applicationDidBecomeActive is called multiple times (each time the app becomes active). If you want to stop responding to this notification after the first time, you could unsubscribe from it as soon as you receive it first time:

@objc
func initateSync {
    // do something first time
    // ...

    // unsubscribe to not receive it anymore
    NotificationCenter.default.removeObserver(self,
        name: NSNotification.Name(rawValue: NOTIF_CONTACT_ENTITY_CHANGE),
        object: nil)    
}

This is what you do in real world after receiving a newspaper trial that you didn't like :)

battlmonstr
  • 5,841
  • 1
  • 23
  • 33