如何限制NSNotification在iOS中多次调用方法?

时间:2018-03-10 07:45:37

标签: ios objective-c swift nsnotificationcenter addobserver

我正在使用NSNotificationCenter在我的代码中发送本地通知,并在Objective-C和Swift中工作。我正在发布Objective-C的通知并在Swift中接收。但是我在通知中添加的方法被多次调用,并且仅在viewDidLoad方法中添加了观察者。

夫特:

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

目标-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];
}

我在我的deinit中添加了删除观察者,但它甚至没有调用。如何多次停止呼叫。

3 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分:0)

你可以这样做

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

viewDidLoad

中添加上述方法
deinit {
        NotificationCenter.default.removeObserver(self)
}

参考:Where to remove observer for NSNotification in Swift?

更新:

检查类实例是否已经存在,即 在您实例化此视图控制器时查看 你可以这样做

if let vc = yourNotificationViewCointrollerObj {
    // USE EXISTING ONE
} else {
    // CREATE NEW INSTANCE
}

答案 2 :(得分:0)

NSNotificationCenter是一个"发布 - 订阅"每个发布的通知都发送给所有订阅者(称为观察者)的机制。如果您多次收到通知,则表示您拥有多个订阅者,或者您要多次发送通知。

我假设每个通知类型只有一个订阅者 - Swift中的MainScreen UIViewController。这意味着您可能会多次发送每个通知。

例如,applicationDidBecomeActive被多次调用(每次应用程序变为活动状态时)。如果您想在第一次之后停止回复此通知,您可以在第一次收到该通知后立即取消订阅:

@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)    
}

这是你在收到一份你不喜欢的报纸试验后在现实世界中所做的事情:)