简体   繁体   English

如何在Swift iOS中注销NSNotification

[英]How to unregister an NSNotification in Swift iOS

I have two controllers 我有两个控制器

class CtrlA: UIViewController {
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        NotificationCenter.default.addObserver(CtrlB.self, selector: #selector(CtrlB.badge(notification:)), name: NSNotification.Name(rawValue: "badge"), object: nil)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        NotificationCenter.default.removeObserver(CtrlB.self, name: NSNotification.Name(rawValue: "badge"), object: nil)
    }
}

class CtrlB: UIViewController {
    static func badge (notification: NSNotification) {
        // blah blah
    }
}

Whats the correct way to unregister the notification listener above? 注销上面的通知侦听器的正确方法是什么? I'm not certain this is correct: NotificationCenter.default.removeObserver(CtrlB.self, name: NSNotification.Name(rawValue: "badge"), object: nil) 我不确定这是正确的: NotificationCenter.default.removeObserver(CtrlB.self, name: NSNotification.Name(rawValue: "badge"), object: nil)

I don't think I can use self either, since it was registered on CtrlB.self 我也不认为可以使用self ,因为它是在CtrlB.selfCtrlB.self

I am not sure why you are registering/unregistering to notifications with a class and not an instance. 我不确定为什么要使用类而不是实例来注册/注销通知。 'CtrlB.self' - will not give you an instance of the CtrlB class, in fact it will return a class itself. 'CtrlB.self'-不会为您提供CtrlB类的实例,实际上它将返回一个类本身。 Instead you should use something like this: 相反,您应该使用以下内容:

class CtrlA {

    let ctrlBInstance = CtrlB()

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        NotificationCenter.default.addObserver(ctrlBInstance, selector: #selector(CtrlB.badge(notification:)), name: NSNotification.Name(rawValue: "badge"), object: nil)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        NotificationCenter.default.removeObserver(ctrlBInstance, name: NSNotification.Name(rawValue: "badge"), object: nil)
    }
}

And your ClassB should look like this in this case: 在这种情况下,您的ClassB应该看起来像这样:

class CtrlB {
   func badge (notification: NSNotification) {
        // blah blah
    }
}

So the best way to implement the notification in your project is create one class called NotificationManager inside that declare one dictionary in which you can always update the observers 因此,在项目中实现通知的最佳方法是在内部创建一个称为NotificationManager类,该类声明一本词典,您可以在其中始终更新观察者

class NotificationManager {
var observers = [String: AnyObject]()
}

Create addObserver method, post notification method and remove observer method inside the same class. 在同一类中创建addObserver方法,发布通知方法并删除观察者方法。

func postNotification(_ name: String, userInfo: [AnyHashable: Any]? = nil) {
    NotificationCenter.default.post(name: name, object: nil, userInfo: userInfo)
}

func addObserver(_ name: String, block: @escaping (Notification) -> Void) {
 //if observer is already in place for this name, remove it
  removeObserverForName(name)
  let observer = NotificationCenter.default.addObserver(forName: name), object: nil, queue: OperationQueue.main, using: block)
  self.observers[name] = observer
}

func removeObserver(_ name: name) {
 guard let observer = self.observers[name] else { return }
 NotificationCenter.default.removeObserver(observer)
 self.observers.removeValue(forKey: name)
}

 //Removes all observers
func removeAllObservers() {
for observer in self.observers.values {
 NotificationCenter.default.removeObserver(observer)
 }self.observers = [:]
}

So access the above method in any of your class wherever its required and it will take care of everything. 因此,在您需要的任何类中访问上述方法,无论需要使用什么方法,它都会处理一切。 This will also prevent crash in your code. 这也可以防止代码崩溃。 If try to remove the same observer more than one time. 如果尝试多次删除同一观察者。

You need to get the instance of the observer,which you haven't declared... 您需要获取未声明的观察者实例。

for instance you need to set class variable secondA... 例如,您需要设置类变量secondA ...

class CtrlA: UIViewController {

var secondController: CtrlB?


override func viewDidLoad()
{
super.viewDidLoad()

    if let unwrappedController = storyboard.instantiateViewController(withIdentifier: "someViewController") as? CtrlB
    {
    secondController = unwrappedController        
    }

}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    if let secondController = secondController
    {
    NotificationCenter.default.addObserver(CtrlB.self, selector: #selector(CtrlB.badge(notification:)), name: NSNotification.Name(rawValue: "badge"), object: nil)
    }
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    if let secondController = secondController
    {
    NotificationCenter.default.removeObserver(CtrlB.self, name: NSNotification.Name(rawValue: "badge"), object: nil)
    }
}

//Also don't forget to remove listening on deinit

deinit
{
    if let secondController = secondController
    {
    NotificationCenter.default.removeObserver(secondController, name: NSNotification.Name(rawValue: "badge"), object: nil)
    }
  }
}

    class CtrlB: UIViewController {
        //Here you go with notification...
        static func badge (notification: NSNotification) {
            // blah blah
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM