如何在Swift iOS中取消注册NSNotification

时间:2017-07-26 17:53:44

标签: ios swift nsnotificationcenter

我有两个控制器

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上注册

3 个答案:

答案 0 :(得分:2)

我不确定您为什么要注册/取消注册具有类而非实例的通知。 ' CtrlB.self' - 不会给你一个CtrlB类的实例,实际上它会返回一个类本身。 相反,你应该使用这样的东西:

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

答案 1 :(得分:2)

  

因此,在项目中实现通知的最佳方法是在里面创建一个名为class NotificationManager { var observers = [String: AnyObject]() } 的类,声明一个字典,您可以随时更新观察者

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 = [:]
}
  

创建addObserver方法,发布通知方法并删除   同一类中的观察者方法。

 for x in range(gen_num+1):
    print(gen_number,"\t\t",juveniles_pop,"\t\t",adults_pop,"\t\t",seniles_pop,"\t\t",juveniles_pop+adults_pop+seniles_pop)
    gen_number+=1
    seniles_pop = (seniles_pop * seniles_surv) + (adults_pop * adults_surv)
    juveniles_pop1 = adults_pop * birth_rate
    adults_pop = juveniles_pop * juveniles_surv
    juveniles_pop = juveniles_pop1
  

因此,无论何处需要,都可以在任何一个类中访问上述方法,它将处理所有事情。这也可以防止代码崩溃。如果尝试多次删除同一个观察者。

答案 2 :(得分:1)

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

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