kmypwn kmypwn - 3 months ago 8
Swift Question

Segue won't trigger after Facebook login with Swift

Thanks in advance for your help!

I am implementing facebook login on a swift app I'm writing, and I am having some trouble performing a segue after the login completes.

As part of FBSDKLoginButtonDelegate, I have two methods:

func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result:
FBSDKLoginManagerLoginResult!, error: NSError!)
{}


and

func loginButtonDidLogOut(loginButton: FBSDKLoginButton!)
{}


The login button is implemented correctly, I am able to read permissions/FB tokens, and pass this onto Amazon Cognito.

The strange thing, though, is that I cannot programmatically segue out of the login, into a different view (controller).

Pushing the FB Login Button takes the user to a web browser (the Facebook SDK handles all of this), and the login takes place.

If I place a segue, like:

dispatch_async(dispatch_get_main_queue(), {
self.performSegueWithIdentifier("segueLoginViewtoHome", sender: nil })


into loginButton(), it never truly executes (i.e, when the web browser goes away, the user is returned to the view with the login button, not the new view intended by the segue). I believe the line executes before the browser window returns to the view housing the login button (and the segue), but I have no clue how to tell the program to "wait" for the view to become the only one active and visible again to perform the segue.

I believe this is the case, because if I were to put the same segue code into loginButtonDidLogOut(), where no switch to a browser is needed, the segue executes just fine after "log out" is pushed in the sheet that slides up from the bottom of the screen.

This view controller is correctly set as the delegate, as shown by the segue functioning correctly if coded to occur upon logout.

Any help would be much appreciated, apologies for the long question, and thanks!

Answer

I fixed this problem by creating a global boolean called fbLoginSuccess initialized to false. If the Facebook login was successful then I set fbLoginSuccess to true where you are performing your segue. Then I overrode viewDidAppear() and perform the segue there if fbLoginSuccess is true. This fixes it because viewDidAppear() is executed after returning from browser window, which is what you want.

var fbLoginSuccess = false

override func viewDidAppear(animated: Bool) {
    if (FBSDKAccessToken.currentAccessToken() != nil || fbLoginSuccess == true)
    {
        performSegueWithIdentifier("loginSegue", sender: self)
    }
}

func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
    print("User Logged In")

    if ((error) != nil) {
        // Process error
    }
    else if result.isCancelled {
        // Handle cancellations
    }
    else {
        fbLoginSuccess = true
        // If you ask for multiple permissions at once, you
        // should check if specific permissions missing
        if result.grantedPermissions.contains("email") {
            // Do work
        }
    }
}

Hope it helps!