FBSDKLoginManager.loginWithReadPermissions does not call handler on iOS
Simplified code:
func login() {
NSLog("Will login with read permissions")
FBSDKLoginManager().logInWithReadPermissions(
["public_profile"],
handler: {
(result: FBSDKLoginManagerLoginResult!, error: NSError!) -> Void in
NSLog("Handler is called")
})
NSLog("Returning from login")
}
When called, it issues the following log statements:
2015-05-25 11:35:07.886 MyApp[1213:646722] Will login with read permissions
2015-05-25 11:44:22.048 MyApp[1213:646722] Returning from login
(The big time difference between the above instructions is because I'm using the debugger to perform internal logInWithReadPermissions operations. Working without the debugger does not change the behavior.)
I tried this on a device with a built-in Facebook app and I logged in and I tried this on a device with no native app where I never accessed Facebook at all. I have also tried this on simulators. I am getting the same result.
I assume this is a synchronous call, but just in case I tried to wait indefinitely in the calling thread - the handler is still never called and nothing is visible on it.
I've included all the entries I could find:
FBSDKSettings.setLoggingBehavior(
[FBSDKLoggingBehaviorAppEvents,
FBSDKLoggingBehaviorInformational,
FBSDKLoggingBehaviorAccessTokens,
FBSDKLoggingBehaviorUIControlErrors,
FBSDKLoggingBehaviorGraphAPIDebugWarning,
FBSDKLoggingBehaviorGraphAPIDebugInfo,
FBSDKLoggingBehaviorNetworkRequests,
FBSDKLoggingBehaviorCacheErrors,
FBSDKLoggingBehaviorDeveloperErrors])
Then, on startup, I get either this:
2015-05-25 11:35:01.320 MyApp[1213:646722] FBSDKLog: Request <#1111>:
URL: https://graph.facebook.com/v2.3
Method: POST
UserAgent: FBiOSSDK.4.1.0
MIME: multipart/form-data; boundary=3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f
Body (w/o attachments):
batch_app_id: 140xxxxxxxxxxxxx
batch: [{"relative_url":"140xxxxxxxxxxxxx?debug=info&fields=app_events_feature_bitmask%2Cname%2Cios_dialog_configs%2Csupports_implicit_sdk_logging%2Cgdpv4_nux_enabled%2Cgdpv4_nux_content%2Cios_supports_system_auth%2Cios_sdk_error_categories&format=json&include_headers=false&sdk=ios","method":"GET"},{"relative_url":"140xxxxxxxxxxxxx?debug=info&fields=app_events_feature_bitmask%2Cname%2Cios_dialog_configs%2Csupports_implicit_sdk_logging%2Cgdpv4_nux_enabled%2Cgdpv4_nux_content%2Cios_supports_system_auth%2Cios_sdk_error_categories&format=json&include_headers=false&sdk=ios","method":"GET"}]
2015-05-25 11:35:01.321 MyApp[1213:646722] FBSDKLog: Request <#1111>:
URL: https://graph.facebook.com/v2.3
Method: POST
UserAgent: FBiOSSDK.4.1.0
MIME: multipart/form-data; boundary=3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f
2015-05-25 11:35:01.329 MyApp[1213:646722] FBSDKLog: FBSDKTimeSpentData Restore: {"numInterruptions":0,"lastSuspendTime":1432544336,"secondsSpentInCurrentSession":3}
2015-05-25 11:35:01.363 MyApp[1213:646722] FBSDKLog: FBSDKAppEvents: Recording event @ 1432578901: {
"_eventName" = "fb_mobile_activate_app";
"_logTime" = 1432578901;
"_ui" = UIAlertController;
"fb_mobile_launch_source" = Unclassified;
}
2015-05-25 11:35:01.364 MyApp[1213:646722] FBSDKLog: FBSDKAppEvents Persist: Read 0 event states. First state has 0 events
2015-05-25 11:35:01.364 MyApp[1213:646722] FBSDKLog: FBSDKAppEvents Persist: Clearing
2015-05-25 11:35:01.365 MyApp[1213:646722] FBSDKLog: FBSDKAppEvents: Recording event @ 1432578901: {
"_eventName" = "fb_mobile_deactivate_app";
"_logTime" = 1432578901;
"_ui" = UIAlertController;
"_valueToSum" = 3;
"fb_mobile_app_interruptions" = 0;
"fb_mobile_launch_source" = Unclassified;
"fb_mobile_time_between_sessions" = "session_quanta_5";
}
2015-05-25 11:35:01.781 MyApp[1213:646722] FBSDKLog: FBSDKURLConnection <#1114>:
Duration: 460 msec
Response Size: 1 kB
MIME type: application/json
2015-05-25 11:35:01.783 MyApp[1213:646722] FBSDKLog: Response <#1111>
Duration: 461 msec
Size: 2011 kB
Response Body:
(
{
body = {
"app_events_feature_bitmask" = 1;
"gdpv4_nux_content" = "New! You're in control - choose what info you want to share with apps.";
"gdpv4_nux_enabled" = 0;
id = 140xxxxxxxxxxxxx;
"ios_dialog_configs" = {
data = (
{
name = like;
url = "/connect/dialog/MPlatformLikeJSDialog";
versions = (
20140410
);
},
{
name = appinvites;
url = "/connect/dialog/MPlatformAppInvitesJSDialog";
versions = (
20140410
);
}
);
};
"ios_sdk_error_categories" = (
{
items = (
{
code = 102;
},
{
code = 190;
}
);
name = login;
"recovery_message" = "Please log into this app again to reconnect your Facebook account.";
"recovery_options" = (
OK,
Cancel
);
},
{
items = (
{
code = 341;
},
{
code = 9;
},
{
code = 2;
},
{
code = 4;
},
{
code = 17;
}
);
name = transient;
"recovery_message" = "The server is temporarily busy, please try again.";
"recovery_options" = (
OK
);
}
);
"ios_supports_system_auth" = 1;
name = MyApp;
"supports_implicit_sdk_logging" = 1;
};
code = 200;
},
{
body = {
"app_events_feature_bitmask" = 1;
"gdpv4_nux_content" = "New! You're in control - choose what info you want to share with apps.";
"gdpv4_nux_enabled" = 0;
id = 140xxxxxxxxxxxxx;
"ios_dialog_configs" = {
data = (
{
name = like;
url = "/connect/dialog/MPlatformLikeJSDialog";
versions = (
20140410
);
},
{
name = appinvites;
url = "/connect/dialog/MPlatformAppInvitesJSDialog";
versions = (
20140410
);
}
);
};
"ios_sdk_error_categories" = (
{
items = (
{
code = 102;
},
{
code = 190;
}
);
name = login;
"recovery_message" = "Please log into this app again to reconnect your Facebook account.";
"recovery_options" = (
OK,
Cancel
);
},
{
items = (
{
code = 341;
},
{
code = 9;
},
{
code = 2;
},
{
code = 4;
},
{
code = 17;
}
);
name = transient;
"recovery_message" = "The server is temporarily busy, please try again.";
"recovery_options" = (
OK
);
}
);
"ios_supports_system_auth" = 1;
name = MyApp;
"supports_implicit_sdk_logging" = 1;
};
code = 200;
}
)
2015-05-25 11:35:01.841 MyApp[1213:646722] FBSDKLog: Dynamically loaded library at /System/Library/Frameworks/Accounts.framework/Accounts
or that:
2015-05-25 12:04:59.336 MyApp[1221:650047] FBSDKLog: FBSDKTimeSpentData Restore: {"numInterruptions":0,"lastSuspendTime":1432544336,"secondsSpentInCurrentSession":3}
2015-05-25 12:04:59.343 MyApp[1221:650047] FBSDKLog: FBSDKAppEvents: Recording event @ 1432580699: {
"_eventName" = "fb_mobile_activate_app";
"_logTime" = 1432580699;
"_ui" = UIAlertController;
"fb_mobile_launch_source" = Unclassified;
}
2015-05-25 12:04:59.344 MyApp[1221:650047] FBSDKLog: FBSDKAppEvents Persist: Read 0 event states. First state has 0 events
2015-05-25 12:04:59.344 MyApp[1221:650047] FBSDKLog: FBSDKAppEvents Persist: Clearing
2015-05-25 12:04:59.345 MyApp[1221:650047] FBSDKLog: FBSDKAppEvents: Recording event @ 1432580699: {
"_eventName" = "fb_mobile_deactivate_app";
"_logTime" = 1432580699;
"_ui" = UIAlertController;
"_valueToSum" = 3;
"fb_mobile_app_interruptions" = 0;
"fb_mobile_launch_source" = Unclassified;
"fb_mobile_time_between_sessions" = "session_quanta_5";
}
Anyway, my handler is never called, but the logInWithReadPermissions function returns ok.
In my AppDelegate, I did all of the following:
func application(application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
FBSDKApplicationDelegate.sharedInstance().application(
application,
didFinishLaunchingWithOptions: launchOptions)
}
func applicationDidBecomeActive(application: UIApplication) {
FBSDKAppEvents.activateApp()
}
func application(application: UIApplication,
openURL url: NSURL,
sourceApplication: String?,
annotation: AnyObject?) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(
application,
openURL: url,
sourceApplication: sourceApplication,
annotation: annotation)
}
I have these lines in my Info.plist:
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>fb140xxxxxxxxxxxxx</string>
</array>
</dict>
</array>
<key>FacebookAppID</key>
<string>140xxxxxxxxxxxxx</string>
<key>FacebookDisplayName</key>
<string>MyApp</string>
Anything I am missing in the above? If not, how can I debug this further? Any log that I can turn on or off? Anything in my app's settings on the Xcode or Facebook side, can anyone think of what I can look at?
source to share
You said:
"I tried to wait indefinitely in the calling thread - the handler still isn't called and nothing is visible on the device."
The call is definitely not synchronous, and if you keep the main thread busy in a closed waiting loop, then it won't be able to "call you back".
Another thing to check is to make sure your app delegate doesn't implement either
func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
If you implement this method in your application, then the other implementation will be ignored:
func application(application: UIApplication,
openURL url: NSURL,
sourceApplication: String?,
annotation: AnyObject?) -> Bool
source to share
I ran into this same problem and noticed that the code I was working with contains two openURL methods defined in the application delegate:
func application(app: UIApplication,
openURL url: NSURL,
options: [String : AnyObject]) -> Bool
and
func application(application: UIApplication,
openURL url: NSURL,
sourceApplication: String?,
annotation: AnyObject?) -> Bool
Removing the first definition resulted in a second call to the login handler. (Basically what paddlefish said).
This is most likely due to the way FBSDKApplicationDelegate
openURL handles requests.
source to share