如何在 Swift iOS 中注销 NSNotification

How to unregister an NSNotification in Swift iOS

我有两个控制器

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

注销上述通知监听器的正确方法是什么? 我不确定这是正确的: NotificationCenter.default.removeObserver(CtrlB.self, name: NSNotification.Name(rawValue: "badge"), object: nil)

我也不认为我可以使用 self,因为它是在 CtrlB.self

上注册的

我不确定您为什么 registering/unregistering 收到带有 class 而不是实例的通知。 'CtrlB.self' - 不会为您提供 CtrlB class 的实例,实际上它会 return 一个 class 本身。 相反,你应该使用这样的东西:

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

在这种情况下,您的 ClassB 应如下所示:

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

您需要获取您尚未声明的观察者实例...

例如你需要设置 class 变量 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
        }
    }

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

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

Create addObserver method, post notification method and remove observer method inside the same class.

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.