首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Swift使协议扩展成为通知观察者

Swift使协议扩展成为通知观察者
EN

Stack Overflow用户
提问于 2015-10-09 01:40:44
回答 5查看 8.6K关注 0票数 25

让我们考虑一下下面的代码:

代码语言:javascript
复制
protocol A {
    func doA()
}

extension A {
  func registerForNotification() {
      NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardDidShow:"), name: UIKeyboardDidShowNotification, object: nil)
  }

  func keyboardDidShow(notification: NSNotification) {

  }
}

现在来看一个实现A的UIViewController子类:

代码语言:javascript
复制
class AController: UIViewController, A {
   override func viewDidLoad() {
      super.viewDidLoad()
      self.registerForNotification()
      triggerKeyboard()
   }

   func triggerKeyboard() {
      // Some code that make key board appear
   }

   func doA() {
   }
}

但令人惊讶的是,这段代码崩溃时出现了一个错误:

keyboardDidShow:]:无法识别的选择器已发送到实例0x7fc97adc3c60

那么,我应该在视图控制器本身中实现观察者吗?它不能留在分机里吗?

以下是已经尝试过的东西。

让A成为一个类协议。将keyboardDidShow作为签名添加到协议本身。

代码语言:javascript
复制
protocol A:class {
   func doA()
   func keyboardDidShow(notification: NSNotification)
}
EN

回答 5

Stack Overflow用户

发布于 2016-01-19 11:56:33

我通过实现NSNotificationCenter的较新的- addObserverForName:object:queue:usingBlock:方法并直接调用该方法解决了类似的问题。

代码语言:javascript
复制
extension A where Self: UIViewController  {
    func registerForNotification() {
        NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardDidShowNotification, object: nil, queue: nil) { [unowned self] notification in
            self.keyboardDidShow(notification)
        }
    }

    func keyboardDidShow(notification: NSNotification) {
        print("This will get called in protocol extension.")
    }
}

此示例将导致在协议扩展中调用keyboardDidShow

票数 34
EN

Stack Overflow用户

发布于 2017-03-10 19:47:36

除了詹姆斯·保兰托尼奥的回答。可以使用关联的对象来实现unregisterForNotification方法。

代码语言:javascript
复制
var pointer: UInt8 = 0

extension NSObject {
    var userInfo: [String: Any] {
        get {
            if let userInfo = objc_getAssociatedObject(self, &pointer) as? [String: Any] {
                return userInfo
            }
            self.userInfo = [String: Any]()
            return self.userInfo
        }
        set(newValue) {
            objc_setAssociatedObject(self, &pointer, newValue, .OBJC_ASSOCIATION_RETAIN)
        }
    }
}

protocol A {}
extension A where Self: UIViewController {

    var defaults: NotificationCenter {
        get {
            return NotificationCenter.default
        }
    }

    func keyboardDidShow(notification: Notification) {
        // Keyboard did show
    }

    func registerForNotification() {
        userInfo["didShowObserver"] = defaults.addObserver(forName: .UIKeyboardDidShow, object: nil, queue: nil, using: keyboardDidShow)
    }

    func unregisterForNotification() {
        if let didShowObserver = userInfo["didShowObserver"] as? NSObjectProtocol {
            defaults.removeObserver(didShowObserver, name: .UIKeyboardDidShow, object: nil)
        }
    }
}
票数 3
EN

Stack Overflow用户

发布于 2015-10-25 07:00:03

要避免崩溃,请在使用该协议的Swift类中实现观察者方法。

实现必须在Swift类本身中,而不仅仅是协议扩展,因为选择器总是引用Objective-C方法,而协议扩展中的函数不能用作Objective-C选择器。但是,如果Swift类继承自Objective-C类,则Swift类中的方法可用作Objective-C选择器

“If your Swift class inherits from an Objective-C class, all of the methods and properties in the class are available as Objective-C selectors.”

此外,在Xcode7.1中,当在addObserver调用中将self指定为观察者时,必须将其向下转换为AnyObject

代码语言:javascript
复制
protocol A {
    func doA()
}

extension A {
    func registerForNotification() {
        NSNotificationCenter.defaultCenter().addObserver(self as! AnyObject,
            selector: Selector("keyboardDidShow:"),
            name: UIKeyboardDidShowNotification,
            object: nil)
    }

    func keyboardDidShow(notification: NSNotification) {
        print("will not appear")
    }
}

class ViewController: UIViewController, A {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.registerForNotification()
        triggerKeyboard()
    }

    func triggerKeyboard(){
        // Some code that makes the keyboard appear
    }

    func doA(){
    }

    func keyboardDidShow(notification: NSNotification) {
        print("got the notification in the class")
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33022540

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档