Unrecognised selector sent to instance causing app crash

Ok so after the user fills out their details in the Sign in view controller my app crashes after tapping the sign in button; and throws me this error:

'unrecognised selector sent to instance.'

This is what it looks like in my sign in VC.

override func viewDidLoad() {
        super.viewDidLoad()
        /
        print("Sign in loading")
       
        didSignInObserver =  NotificationCenter.default.addObserver(forName: NSNotification.Name.AWSIdentityManagerDidSignIn,
        object: AWSIdentityManager.defaultIdentityManager(),
        queue: OperationQueue.main,
        using: {(note: Notification) -> Void in
        /
        })
       
        /
        customSignInProviderButton.addTarget(self, action: Selector(("handleCustomSignIn")), for: .touchUpInside)
        customCreateNewAccountButton.addTarget(self, action: Selector(("handleUserPoolSignUp")), for: .touchUpInside)
        customForgotUserPassword.addTarget(self, action: Selector(("handleUserPoolForgotPassword")), for: .touchUpInside)
        customSignInProviderButton.addTarget(self, action: Selector(("UserLogIn")), for: .touchUpInside)
       
        /
        let toolBar = UIToolbar()
        toolBar.sizeToFit()
       
        let flexibleSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
       
        let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.done, target: self, action: #selector(self.doneClicked))
       
        toolBar.setItems([flexibleSpace, doneButton], animated: false)
       
        customUserIdField.inputAccessoryView = toolBar
        customPasswordField.inputAccessoryView = toolBar
    }
Answered by OOPer in 201519022

Your code is completely broken. You have said you have redeclared your function as `@objc func handleCustomSignIn() {...}`, but there's no method named `handleCustomSignIn` in your code.


When you write `addTarget`, you need to implement all methods specified in `selector: ...`.

Update your code implementing all the action methods you need and come again with your updated code.

I lack information to be sure, but if handleCustomSignIn has a parameter, you should tell it to selector :


Selector(("handleCustomSignIn:"))


Nota: syntax for selector should be better with :


#selector(handleCustomSignIn(_:)) or #selector(handleCustomSignIn(param:)) if the parameter has a name

My selectors don't need any parameters as they are only meant to move to the next view controller.

I have other selectors and they all work except for this one

Seeing your code, you have added two targets for the same object `customSignInProviderButton` and the same event `.touchUpInside`.


So, your VC needs to have two methods:

    @objc func handleCustomSignIn() {
        //...
    }

And:

    @objc func UserLogIn() {
        //...
    }


Any of the two `customSignInProviderButton.addTarget(self, ...)` may be a mistake, but to make your current code work, both methods needed.

And as already noted, both methods cannot have any parameters.


By the way, in Swift 3, you'd better use `#selector` notation (like in your `doneButton` declaration), rather than using initializer of `Selector`.

When you use an unimplemented method in a `#selector` notation, Xcode or Swift will tell you that while editing, or at least compiletime.

I have tried redeclaring my functions as the following:

@objc func handleCustomSignIn() {
     //...
}

But still nothing has changed.

Where is `UserLogIn` ? You'd better show whole your VC, which can reproduce the issue. Without showing all we need, a long guess game would go on...

Righto then here is the entire View Controller.


import UIKit
import AWSMobileHubHelper
import FBSDKCoreKit
import FBSDKLoginKit
class SignInViewController: UIViewController {
   
        var didSignInObserver: AnyObject!
        var passwordAuthenticationCompletion: AWSTaskCompletionSource<AnyObject>?
   
    @IBOutlet weak var customUserIdField: UITextField!
    @IBOutlet weak var customPasswordField: UITextField!
    @IBOutlet weak var customCreateNewAccountButton: UIButton!
    @IBOutlet weak var customForgotUserPassword: UIButton!
    @IBOutlet weak var customSignInProviderButton: UIButton!
    @IBOutlet weak var facebookLoginButton: FBSDKLoginButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        print("Sign in loading")
       
        didSignInObserver =  NotificationCenter.default.addObserver(forName: NSNotification.Name.AWSIdentityManagerDidSignIn,
        object: AWSIdentityManager.defaultIdentityManager(),
        queue: OperationQueue.main,
        using: {(note: Notification) -> Void in
        customSignInProviderButton.addTarget(self, action: Selector(("handleCustomSignIn")), for: .touchUpInside)
        customCreateNewAccountButton.addTarget(self, action: Selector(("handleUserPoolSignUp")), for: .touchUpInside)
        customForgotUserPassword.addTarget(self, action: Selector(("handleUserPoolForgotPassword")), for: .touchUpInside)
        customSignInProviderButton.addTarget(self, action: Selector(("UserLogIn")), for: .touchUpInside)
       
        let toolBar = UIToolbar()
        toolBar.sizeToFit()
        let flexibleSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
        let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.done, target: self, action: #selector(self.doneClicked))
        toolBar.setItems([flexibleSpace, doneButton], animated: false)
        customUserIdField.inputAccessoryView = toolBar
        customPasswordField.inputAccessoryView = toolBar
    }
   
    deinit {
        NotificationCenter.default.removeObserver(didSignInObserver)
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
   
    func handleFacebookLogin() {

        AWSFacebookSignInProvider.sharedInstance().setPermissions(["public_profile"]);
        handleLoginWithSignInProvider(signInProvider: AWSFacebookSignInProvider.sharedInstance())
    }


    func handleLoginWithSignInProvider(signInProvider: AWSSignInProvider) {
        Before Editing
        AWSIdentityManager.defaultIdentityManager().loginWithSign(signInProvider, completionHandler:
            {(result, error) -> Void in
                if error == nil {
                    
                    DispatchQueue.main.async(execute: {
                        self.presentingViewController?.dismiss(animated: true, completion: nil)
                    })
                }
                print("Login with signin provider result = \(result), error = \(error)")
        }
       
        AWSIdentityManager.defaultIdentityManager().loginWithSign(signInProvider, completionHandler: {(result, error) -> Void in
            if error == nil {
              
                DispatchQueue.main.async(execute: {
                    self.presentingViewController?.dismiss(animated: true, completion: nil)
                })
            }
            print("Login with sign in provider result = \(result), error =\(error)")
        })
    }
   

    func dismissViewController() {
        self.dismiss(animated: true, completion: nil)
    }
   

    func doneClicked() {
        view.endEditing(true)
    }
}

As I wrote, your `SignInViewController` does not have a method named `UserLogIn`, but you have this line:

customSignInProviderButton.addTarget(self, action: Selector(("UserLogIn")), for: .touchUpInside)


So, when `customSignInProviderButton` is tapped, iOS searches a method named `UserLogIn` inside `self` which is a `SignInViewController`.

But your `SignInViewController` dose not have a method named `UserLogIn`, so iOS terminates with saying 'unrecognised selector sent to instance.'


Remove that line and check what you can find without that line.


And one more.

Your `SignInViewController` does not have methods named `handleUserPoolSignUp` or `handleUserPoolForgotPassword`. That would never work.

But you said they all work except for this one.

Say only truth if you really want to fix your issue.


I was using a template from aws mobile hub and the selectors are used to initialize the buttons.

So how do these work then?

    loginButton.addTarget(self, action: "handleCustomSignIn", forControlEvents: .TouchUpInside)
    createAccountButton.addTarget(self, action: "handleUserPoolSignUp", forControlEvents: .TouchUpInside)
    forgotPassword.addTarget(self, action: "handleUserPoolForgotPassword", forControlEvents: .TouchUpInside)
Accepted Answer

Your code is completely broken. You have said you have redeclared your function as `@objc func handleCustomSignIn() {...}`, but there's no method named `handleCustomSignIn` in your code.


When you write `addTarget`, you need to implement all methods specified in `selector: ...`.

Update your code implementing all the action methods you need and come again with your updated code.

Unrecognised selector sent to instance causing app crash
 
 
Q