Search code examples
swiftnsnotificationcenter

App crashing: Exception - unrecognised selector sent to instance


I've got a UITableviewController with following logic to slide up / down the entire view once the keyboard toggles like so:

class ChatDetailViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
 // variables...

 override func viewDidLoad() {
        super.viewDidLoad()
        // do stuff...
        NotificationCenter.default.addObserver(self, selector: Selector(("keyboardWillShow:")), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: Selector(("keyboardWillHide:")), name: UIResponder.keyboardWillHideNotification, object: nil)
       // do other stuff...
}
...
func keyboardWillShow(notification: NSNotification) {
        if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            self.view.frame.origin.y -= keyboardSize.height
        }
    }

    func keyboardWillHide(notification: NSNotification) {
        self.view.frame.origin.y = 0
    }
...
}

Toggling the keyboard then crashes the App with following exception: ChatDetailViewController keyboardWillShow:]: unrecognized selector sent to instance 0x7f82fc41fdf0

The error message seems clear at first glance but I still can't figure out what's wrong with my selector. No code warnings, no typos,...

What is it I'm doing wrong here?


Solution

  • Three issues:

    • The creation of the selector is wrong (use #selector)
    • The signature of the action is wrong (missing underscore)
    • The action must be marked as @objc

    And the type in Swift is Notification without NS prefix

    override func viewDidLoad() {
        super.viewDidLoad()
        // do stuff...
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
        // do other stuff...
    }
    
        ...
    
    @objc func keyboardWillShow(_ notification: Notification) {
        if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            self.view.frame.origin.y -= keyboardSize.height
        }
    }
    
    @objc func keyboardWillHide(_ notification: Notification) {
        self.view.frame.origin.y = 0
    }
    
    ...