Let's consider the following code:
protocol A {
func doA()
}
extension A {
func registerForNotification() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardDidShow:"), name: UIKeyboardDidShowNotification, object: nil)
}
func keyboardDidShow(notification: NSNotification) {
}
}
Now look at a UIViewController subclass that implements A:
class AController: UIViewController, A {
override func viewDidLoad() {
super.viewDidLoad()
self.registerForNotification()
triggerKeyboard()
}
func triggerKeyboard() {
// Some code that make key board appear
}
func doA() {
}
}
But surprisingly this crashes with an error:
keyboardDidShow:]: unrecognized selector sent to instance 0x7fc97adc3c60
So should I implement the observer in the view controller itself? Can't it stay in the extension?
Following things already tried.
making A a class protocol. Adding keyboardDidShow to protocol itself as signature.
protocol A:class {
func doA()
func keyboardDidShow(notification: NSNotification)
}
I solved a similar problem by implementing the newer - addObserverForName:object:queue:usingBlock:
method of NSNotificationCenter
and calling the method directly.
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.")
}
}
This example will cause keyboardDidShow
to be called in the protocol extension.