iosswiftfacebookgoogle-signin

Implementing both Facebook and Google signIn API in swift 3.0


I have been struggling for a whole night and half a day before giving up and asking here for help. I've read several threads here on Stack Overflow but any solution seems to work but this even though the app crash on startup.

2016-10-26 16:03:58.793 MotivaMe[3997:404331] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<MotivaMe.ViewController 0x7ff1a0407700> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key loginButtonFB.'

FIXED SEE BOTTOM FOR SOLUTION

EDIT: Compiler now says :

"Implementation of application:openURL:sourceApplication:annotation: not found. Please add the handler into your App Delegate."

In particular after the authentication I get stuck and don't get redirected to the app

This is the first time I try to code for iOS so I'm still not that confident with CocoaTouch that I'm still studying right now. Any help is appreciated thanks (an explanation over the fix would really be appreciated since I can't get what's wrong, thanks to everyone)

Here is the AppDelegate.swift

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
{
   
    FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
   
    var configureError: NSError?
    GGLContext.sharedInstance().configureWithError(&configureError)
    assert(configureError == nil, "Error configuring Google services: \(configureError)")
    
    GIDSignIn.sharedInstance().delegate = self
    
    return true
    
}

func application(application: UIApplication, openURL url: NSURL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool
{
    
    let googleDidHandle = GIDSignIn.sharedInstance().handle(
        url as URL!,
        sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String,
        annotation: options[UIApplicationOpenURLOptionsKey.annotation])
    
    let facebookDidHandle = FBSDKApplicationDelegate.sharedInstance().application(
        application,
        open: url as URL!,
        sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String,
        annotation: options [UIApplicationOpenURLOptionsKey.annotation])
    
    return googleDidHandle || facebookDidHandle
}

// The sign-in flow has finished and was successful if |error| is |nil|.
func sign(_ doLoginGoogle: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!)
{
    if (error == nil)
    {
        // Perform any operations on signed in user here.
        let userId = user.userID                  // For client-side use only!
        let idToken = user.authentication.idToken // Safe to send to the server
        let fullName = user.profile.name
        let givenName = user.profile.givenName
        let familyName = user.profile.familyName
        let email = user.profile.email
        // ...
        print(userId,idToken,fullName,givenName,familyName,email)
    }
    else
    {
        print("\(error.localizedDescription)")
    }
}

And here is the ViewController.swift

override func viewDidLoad() {
    super.viewDidLoad()
    
    
    GIDSignIn.sharedInstance().uiDelegate = self
    GIDSignIn.sharedInstance().signInSilently()
}

@IBOutlet weak var doLoginFacebook: FBSDKLoginButton!
@IBOutlet weak var doLoginGoogle: GIDSignInButton!

func loginButtonDidLogOut(_  doLoginFacebook: FBSDKLoginButton!)
{
    print("Did log out of facebook")
}

func loginButton(_ doLoginFacebook: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!)
{
    if error != nil
    {
        print(error)
        return
    }
    else
    {
        if(FBSDKAccessToken.current() != nil) //useless check but want to get confident with the api
        {
            //TODO implement switching pages on login 
            print("Sucessfully logged into facebook!")
        }
    }
}

Solution

  • I strongly suspect, that one of your outlet connection got stuck in your Stroyboard or Nib. This can happen from time to time, so you need to make sure that if you update/delete an outlet connection, you delete from the Interface builder too.

    To fix this, go to your interface editor, and select your viewController. Than go here on the panel of the right hand side.

    enter image description here

    There you should be able to still see the loginButtonFB connected, with a little explanation mark next to it. Delete this connection, it should solve your problem.