JozackOverFlow JozackOverFlow - 4 months ago 62
iOS Question

Facebook login completion block not called

I tried to implement Facebook login with a custom login button, I've completed all the setup steps and when I tap the button, the web view present and ask me to provide the permission.

However, if I tap Done(on top left of web view controller), the completion block is called but when I tap Cancel or OK, the web view controller dismissed but the completion block is never get called?
enter image description here
Here's the code I used:

let fbLoginManager = FBSDKLoginManager()
fbLoginManager.loginBehavior = .Native
fbLoginManager.logInWithReadPermissions(["email"], fromViewController: self) { (result, error) in
// put a breakpoint here but it won't stop here if I tap OK
if error != nil {
print(error.localizedFailureReason)
} else if result.isCancelled {
// dismiss view
} else {
let token = result.token.tokenString
// do something with the token
}
}


EDIT 1

Here's the open url method in AppDelegate:

func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
return application(app, openURL: url, sourceApplication: nil, annotation: [:])
}
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
if url.scheme == Key.FACEBOOK_URL_SCHEME {
let handled = FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
return handled
}
let dynamicLink = FIRDynamicLinks.dynamicLinks()?.dynamicLinkFromCustomSchemeURL(url)
if let dynamicLink = dynamicLink {
if let url = dynamicLink.url {
if let paths = url.pathComponents{
if paths.count > 2 {
let slug = paths[2]
if let book = AppManager.instance.findBookBySlug(slug) {
// Open detail book
self.openDetailBook(book)
} else {
self.openDetailBookWithSlug(slug)
}
}
}
}
}
if url.scheme == Key.DEEP_LINK_URL_SCHEME {
if let paths = url.pathComponents, host = url.host {
if host == "truyen" {
if paths.count > 1 {
let slug = paths[1]
if let book = AppManager.instance.findBookBySlug(slug) {
// Open detail book
self.openDetailBook(book)
} else {
self.openDetailBookWithSlug(slug)
}
}
}
}
}
return true
}

Answer

If you ever face these situation, debug it yourself as Facebook SDK is open source. The window you are seeing is the SFSafariViewController. When you tap on any of those buttons, the call back will be handled by the SFSafariViewController. Look for the SFSafariViewController delegate methods in the Facebook sdk.

Put a breakpoint after you call the login code, and go step by step, it will take you to the class that uses SFSafariViewController.

In one of those delegate methods, you will find a call to the open url method. Implement the same open URL method in the app delegate method.

In your case the issue would be using wrong openURL method. The correct one shud be

func application(application: UIApplication,openURL url: NSURL, options: [String: AnyObject]) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(application, 
     openURL: url, 
     sourceApplication: options[UIApplicationOpenURLOptionsSourceApplicationKey] as! String,
     annotation: options [UIApplicationOpenURLOptionsAnnotationKey])
}