Lalo Lalo - 1 year ago 134
Swift Question

Facebook Login iOS 10 works until button is pressed for a second time

I've been creating a custom button for Facebook Login on iOS 10 using Swift 3. Unfortunately Facebook login won't show the SafariViewController until I press the UIButton for the second time. Thanks to breakpoints I know it calls loginManager.logIn() but it never enters the callback until the second time I press the UIButton. Although if I use a FacebookLoginButton() alongside my custom everything works. I really have no idea what's the problem. Hope you can help me. Thanks!

Here's my ViewController:

import UIKit
import FacebookCore
import FacebookLogin

class ViewController: UIViewController {

override func viewDidLoad() {

self.view.backgroundColor = .blue

// Add a custom login button to your app
let myLoginButton = UIButton(type: .system)
myLoginButton.backgroundColor = .red
myLoginButton.frame = CGRect(x: 0, y: 0, width: 180, height: 40) =;
myLoginButton.setTitle("My Button", for: .normal)

// Handle clicks on the button
myLoginButton.addTarget(self, action: #selector(self.loginButtonClicked), for: .touchUpInside)

// Add the button to the view

// Once the button is clicked, show the login dialog
func loginButtonClicked() {
let loginManager = LoginManager()
loginManager.logIn([.publicProfile], viewController: self) { (loginResult) in
switch loginResult {
case .failed(let error):
case .cancelled:
print("User cancelled login.")
case .success(let grantedPermissions, let declinedPermissions, let accessToken):
print("Logged in!")

And my info.plist (The only changes are the placeholders for my app's name and id:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "">
<plist version="1.0">
<string>fb[A Number]</string>
<string>[My Facebook App ID]</string>
<string>[My App Name]</string>

Update: This has been confirmed as a bug by facebook

Answer Source

The problem is related to a method that resides in Facebook SDK

- (void)logInWithBehavior:(FBSDKLoginBehavior)loginBehavior  
  __weak __typeof__(self) weakSelf = self;  
  [FBSDKServerConfigurationManager loadServerConfigurationWithCompletionBlock:^(FBSDKServerConfiguration *serverConfiguration, NSError *loadError) {  
    [weakSelf logInWithBehavior:loginBehavior serverConfiguration:serverConfiguration serverConfigurationLoadError:loadError];  

you will get no login at view because, with your button callback that include the LoginManager init, the FBSDKServerConfigurationManager is null at the first time you press the login button, but is instead init at the second time.

I have resolved a very similar issue, simply declaring the manager as a global variable and making the init of the LoginManager in viewDidLoad.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download