ios - 无法删除协议(protocol)扩展内的NotificationCenter观察者

标签 ios iphone swift xcode

我创建了一个扩展协议(protocol)来“弹出”任何采用它的 View 。当调用 show 并显示 View 时,将在通知中心添加一个检测键盘将显示的观察者。当 View 被关闭时,该观察者应该从默认的通知中心中删除。

不幸的是,这并没有发生。我认为在这种情况下“ self ”不是观察者。我考虑将“addobserver”中返回的观察者保存到变量中,但我不知道如何在协议(protocol)内部进行操作。任何建议将非常感激。这是我的代码:

protocol PopUpProtocol {
    func show()
    func dismiss()

    var dialogHeight:CGFloat {get}
    var backgroundView:UIView {get}
    var dialogView:UIView {get set}
}

extension PopUpProtocol where Self:UIView{
    func show(){
        NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillShow, object: nil, queue: nil) {_ in
            self.keyboardWillShow()
        }
        self.backgroundView.alpha = 0
        self.dialogView.frame = CGRect(x: 0, y: self.frame.height , width: self.frame.width, height: self.dialogHeight)

        UIApplication.shared.delegate?.window??.rootViewController?.view.addSubview(self)
        UIView.animate(withDuration: 0.33, animations: {
            self.backgroundView.alpha = 0.66
            self.dialogView.frame = CGRect(x: 0, y: self.frame.height-self.dialogHeight , width: self.frame.width, height: self.dialogHeight)
        })

    }

    func dismiss(){

        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        UIView.animate(withDuration: 0.33, animations: {
            self.backgroundView.alpha = 0
            self.dialogView.frame = CGRect(x: 0, y: self.frame.height , width: self.frame.width, height: self.dialogHeight)
        }, completion: { (completed) in
            self.removeFromSuperview()
        })
    }

    func keyboardWillShow()
    {
        print("Keyboard will come up")
    }
}

最佳答案

好吧,虽然我无法完全解释细节,但我找到了解决方案。我能够拯救观察者。观察到的结果被存储为关联对象:

var KeyboardShowObserverObjectKey: UInt8 = 1

extension PopUpProtocol where Self:UIView{

var keyboardShowObserverObject: NSObjectProtocol? {
    get {
        return objc_getAssociatedObject(self, &KeyboardShowObserverObjectKey) as? NSObjectProtocol
    }
    set {
        objc_setAssociatedObject(self, &KeyboardShowObserverObjectKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }
}

当我添加观察者时,我然后设置 keyBoardShowObserverObject:

keyboardShowObserverObject = NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillShow, object: nil, queue: nil) { (notification) in
        self.keyboardWillShow()
    }

当我想删除观察者时,我运行这个函数:

private func removeKeyboardObservers() {
    if let keyboardShowObserverObject = keyboardShowObserverObject {
        NotificationCenter.default.removeObserver(keyboardShowObserverObject)
    }
    keyboardShowObserverObject = nil
}

此外,我需要将我的协议(protocol)声明为类绑定(bind):

protocol PopUpProtocol : class {

希望这能帮助任何遇到同样问题的人。

关于ios - 无法删除协议(protocol)扩展内的NotificationCenter观察者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47124545/

相关文章:

ios - 如何存储嵌套字典值

ios - UINavigationController 顶部有一个空隙

iphone - 从使用 AVAssetWriter 创建的视频生成缩略图

ios - Swift 中的协议(protocol)继承 + 委托(delegate)

ios - 使用 UIAlertController 防止键盘自动出现

ios - 地理编码地址未返回正确的坐标

ios - 如何发送固定时间的推送通知?

iphone - 如何使用从 Web 服务返回的以下数据填充 UIImage?

ios - 实现收藏按钮 Swift

ios - 谷歌地图自动完成