2015-08-28 136 views
1

我在视图控制器中有以下代码来注册我的一个自定义通知。我已经使用选择器直到现在注册,但认为我会尝试关闭,并注意到一些奇怪的东西。当Observer被删除时,NSNotification Observer Closure不会被删除?

NSNotificationCenter.defaultCenter().addObserver(self, selector: "notificationReceived:", name: "NotificationKey", object: nil) 
NSNotificationCenter.defaultCenter().addObserverForName("NotificationKey", object: nil, queue: nil) { [weak self] notification in 
    NSLog("Notification received in closure!") 
} 

@objc private func notificationReceived(notification: NSNotification) { 
    NSLog("Notification received!") 
} 

然后我作为观察者删除视图控制器。

NSNotificationCenter.defaultCenter().removeObserver(self) 

一旦观察者被删除,我仍然在Closure中看到NSLog,但在选择器函数中看不到NSLog。通知中心正在关闭关闭。我也注意到,如果self被引用,闭包会导致一个保留周期(添加[weak self]修复了这个问题,但NSLog行仍然被调用)。

有谁知道为什么封闭仍然处理通知?

会不会有一种情况,你会使用选择器上的闭包(我更喜欢它们,因为它避免了魔法字符串)?

回答

6

addObserverForName(_:object:queue:usingBlock:)实际上返回一个对象,你可以坚持。这是你应该通过removeObserver()这个对象。

var observer: AnyObject? 

// ... 

observer = NSNotificationCenter.defaultCenter().addObserverForName("NotificationKey", object: nil, queue: nil) { [weak self] notification in 
    NSLog("Notification received in closure!") 
} 

// ... 

if let observer = observer { 
    NSNotificationCenter.defaultCenter().removeObserver(observer) 
} 
+0

稍作修改:在将它传递给'removeObserver(_ :)'之前,必须展开'observer',因为您声明它是可选的。 –

+0

哎呀,好的。谢谢。 – jtbandes

+0

啊,呵呵。没有看到它返回的东西。谢谢!我现在可以转换我的选择器! (我讨厌选择器:P) – lionpants