52

I have updated iPhone 6 plus to iOS 9 beta and trying to perform Facebook login but each time its presenting UIWebView with Facebook login form.

I have Facebook sdk

FB_IOS_SDK_VERSION_STRING @"3.24.0"
FB_IOS_SDK_TARGET_PLATFORM_VERSION @"v2.2"

And I am using following methods to perform Facebook Login

    NSArray *permissions = @[@"email",@"user_birthday",@"public_profile"];


     FBSessionStateHandler completionHandler = ^(FBSession *session, FBSessionState status, NSError *error) {
         [self sessionStateChanged:session state:status error:error];
     };

     if ([FBSession activeSession].state == FBSessionStateCreatedTokenLoaded) {
     // we have a cached token, so open the session
         [[FBSession activeSession]openWithBehavior:FBSessionLoginBehaviorUseSystemAccountIfPresent
                                 fromViewController:nil
                                  completionHandler:completionHandler];
     } else {

     [self clearAllUserInfo];
    [[NSURLCache sharedURLCache] removeAllCachedResponses];

     // create a new facebook session
     FBSession *fbSession = [[FBSession alloc] initWithPermissions:permissions];
     [FBSession setActiveSession:fbSession];
     [fbSession openWithBehavior:FBSessionLoginBehaviorUseSystemAccountIfPresent
              fromViewController:nil
               completionHandler:completionHandler];
     }

I have following setting under plist file

    <key>LSApplicationQueriesSchemes</key>
    <array>
        <string>fbapi</string>
        <string>fbapi20130214</string>
        <string>fbapi20130410</string>
        <string>fbapi20130702</string>
        <string>fbapi20131010</string>
        <string>fbapi20131219</string>
        <string>fbapi20140410</string>
        <string>fbapi20140116</string>
        <string>fbapi20150313</string>
        <string>fbapi20150629</string>
        <string>fb-messenger-api20140430</string>
        <string>fbauth</string>
        <string>fbauth2</string>
   <array>

Please let me know what I am missing here. First it is checking for iPhone device Setting-> Facebook credentials but never open Facebook app for login. Seems it does not recognize Facebook app installed on device.

swiftBoy
  • 35,607
  • 26
  • 136
  • 135
Bhumeshwer katre
  • 4,671
  • 2
  • 19
  • 29
  • 2
    I noticed this too. I think Facebook decided to default to the webview login over the Facebook app because they didn't like how iOS9 presents these alerts saying "AppName wants to open Facebook" and "Facebook wants to open AppName" the first time it tries to do the app login. – dan Sep 14 '15 at 14:27
  • @dan Thanks for comment. But Instagram app able to open Facebook app for login in iOS 9. So there should be the way to open Facebook App. But not sure what it is ? – Bhumeshwer katre Sep 14 '15 at 14:32
  • Thanks Dan you are right. – Bhumeshwer katre Sep 14 '15 at 17:54
  • 1
    I have same behaviour over here. I'm using latest FB SDK and using LoginWithReadPermissions and going to the webview. – Camilo Aguilar Sep 15 '15 at 03:41
  • I also met similar problem. I tried share to FB on my iPhone, and it opened a new website, and reminded me to download FB app. But when I tried sharing on another iPhone, it opened a share dialog. On my iPhone, it requires open url schemes fbapi20130410 and fbapi20130214. another iPhone doesn't require these schemes – DianeZhou Mar 29 '16 at 02:29

12 Answers12

54

Below is complete process for new "Facebook login".


this is how I have revised my Facebook Login integration to get it work on latest update.

Xcode 7.x , iOS 9 , Facebook SDK 4.x

Step-1. Download latest Facebook SDK (it includes major changes).

Step-2. Add FBSDKCoreKit.framework and FBSDKLoginKit.framework to your project.

Step-3. Now go to Project > Build Phases > add SafariServices.framework

Step-4. There are three changes in info.plist we need to verify.

4.1 Make sure you have below in your info.plist file

<key>CFBundleURLTypes</key>
<array>
  <dict>
  <key>CFBundleURLSchemes</key>
  <array>
    <string><your fb id here eg. fbxxxxxx></string>
  </array>
  </dict>
</array>
  <key>FacebookAppID</key>
  <string><your FacebookAppID></string>
  <key>FacebookDisplayName</key>
<string><Your_App_Name_Here></string>

4.2 Now add below for White-list Facebook Servers, this is must for iOS 9

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSExceptionDomains</key>
  <dict>
    <key>facebook.com</key>
    <dict>
      <key>NSIncludesSubdomains</key>
      <true/>
      <key>NSExceptionRequiresForwardSecrecy</key>
      <false/>
    </dict>
    <key>fbcdn.net</key>
    <dict>
      <key>NSIncludesSubdomains</key>
      <true/>
      <key>NSExceptionRequiresForwardSecrecy</key>
      <false/>
    </dict>
    <key>akamaihd.net</key>
    <dict>
      <key>NSIncludesSubdomains</key>
      <true/>
      <key>NSExceptionRequiresForwardSecrecy</key>
      <false/>
    </dict>
  </dict>
</dict>

4.3 Add URL schemes

<key>LSApplicationQueriesSchemes</key>
  <array>
      <string>fbapi</string>
      <string>fb-messenger-api</string>
      <string>fbauth2</string>
      <string>fbshareextension</string>
  </array>

Step-5. Now open AppDelegate.m file

5.1 Add below import statements, (remove old one).

#import <FBSDKLoginKit/FBSDKLoginKit.h>
 #import <FBSDKCoreKit/FBSDKCoreKit.h>

5.2 update following following methods

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
  return [[FBSDKApplicationDelegate sharedInstance] application:application
                                                         openURL:url
                                               sourceApplication:sourceApplication
                                                      annotation:annotation];
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
  [FBSDKAppEvents activateApp];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  return [[FBSDKApplicationDelegate sharedInstance] application:application
                                    didFinishLaunchingWithOptions:launchOptions];
}

Step-6. Now we need to modify our Login Controller, where we do Login task

6.1 Add these imports in Login ViewController.m

#import <FBSDKCoreKit/FBSDKCoreKit.h>
#import <FBSDKLoginKit/FBSDKLoginKit.h>

6.2 Add Facebook Login Button

FBSDKLoginButton *loginButton = [[FBSDKLoginButton alloc] init];
loginButton.center = self.view.center;
[self.view addSubview:loginButton];

6.3 Handle Login button click

-(IBAction)facebookLogin:(id)sender
{
    FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];

    if ([FBSDKAccessToken currentAccessToken])
    {
        NSLog(@"Token is available : %@",[[FBSDKAccessToken currentAccessToken]tokenString]);
        [self fetchUserInfo];
    }
    else
    {
        [login logInWithReadPermissions:@[@"email"] fromViewController:self handler:^(FBSDKLoginManagerLoginResult *result, NSError *error)
         {
             if (error)
             {
                 NSLog(@"Login process error");
             }
             else if (result.isCancelled)
             {
                 NSLog(@"User cancelled login");
             }
             else
             {
                 NSLog(@"Login Success");

                 if ([result.grantedPermissions containsObject:@"email"])
                 {
                     NSLog(@"result is:%@",result);
                     [self fetchUserInfo];
                 }
                 else
                 {
                     [SVProgressHUD showErrorWithStatus:@"Facebook email permission error"];

                 }
             }
         }];
    }
}

6.4 Get user info (name, email etc.)

-(void)fetchUserInfo
{
    if ([FBSDKAccessToken currentAccessToken])
    {
        NSLog(@"Token is available : %@",[[FBSDKAccessToken currentAccessToken]tokenString]);

        [[[FBSDKGraphRequest alloc] initWithGraphPath:@"me" parameters:@{@"fields": @"id, name, email"}]
         startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
             if (!error)
             {
                 NSLog(@"results:%@",result);

                 NSString *email = [result objectForKey:@"email"];
                 NSString *userId = [result objectForKey:@"id"];

                 if (email.length >0 )
                 {
                     //Start you app Todo
                 }
                 else
                 {
                    NSLog(@“Facebook email is not verified");
                 }
             }
             else
             {
                 NSLog(@"Error %@",error);
            }
         }];
    }
}

Step-7. Now you can build project, you should get below screen.

enter image description here

Hope this will help you guys.

References : Thanks to Facebook docs, Stackoverflow posts and Google.

swiftBoy
  • 35,607
  • 26
  • 136
  • 135
  • Great answer, thanks. `LSApplicationQueriesSchemes` was the critical bit for me - note that if you are still using a pre-v4.6 SDK, this is slightly different: https://developers.facebook.com/docs/ios/ios9 – Dunc Nov 12 '15 at 09:48
  • fb says "The SDK could continue to switch from your app to the Facebook app." from link https://developers.facebook.com/blog/post/2015/10/29/Facebook-Login-iOS9 how can we do that? – Max Nov 16 '15 at 06:22
  • 19
    This is very useful, but the OP asked about launching the app, which this answer doesn't show how to do. It might be nice to explain, in your answer, that that's no longer possible with newest SDKs. – Bjorn Roche Nov 30 '15 at 14:35
  • @Max, I am also looking for something that could do that in FB SDK v4.6. I just can't find anything more helpful. – Adro Dec 09 '15 at 08:59
  • How to handle these cases. * If I logged in Already in Mobile Safari, How FB V 4.6 SDK "FBSDKLoginBehaviorWeb" should perform. * If I already logged in an FB App, How FB V 4.6 SDK "FBSDKLoginBehaviorWeb" should perform. – Femina Dec 09 '15 at 15:17
  • 1
    @AdromilBalais, you can use older version 4.4.0 https://origincache.facebook.com/developers/resources/?id=FacebookSDKs-iOS-20150708.pkg – Max Dec 10 '15 at 05:00
  • Great answer, thanks. I have audited these steps many times but "logInWithReadPermissions" simply never returns. – snakeoil May 04 '16 at 02:10
  • It seems like Facebook suggests using `openURL:sourceApplication...` but in fact that's deprecated in 9.0 – now we should use `app:openURL:options...` – overriding both will result in `logInWithReadPermissions` never returning. – snakeoil May 04 '16 at 04:13
  • Can we redirect link to the Facebook app for authentication? As we are running one app that is redirecting into the app for iOS 8 but I am unable to iOS 9. – Gautam Sareriya Aug 03 '16 at 08:22
  • @ RDC, I have follow all the steps for integrating FB SDK V 4.15. But still in my iPhone 4s with iOS 9.3.2 I am not able to login with SDK. It is redirect on the same login page. The same thing is working in another iPhone 5s with iOS 9.3.5. So is it the iOS version issue or something else ? – ChandreshKanetiya Sep 14 '16 at 07:39
  • Thank you for the solution. This is not related to the same but you might help. I want to know if there is a way to enable Facebook Login without hardcoding the values in info.plist file. Basically what I want to achieve has been mentioned here: https://stackoverflow.com/questions/51153674/ios-how-to-enable-facebook-login-without-hardcoding-the-values-in-info-plist-f – Nitin Srivastava Jul 03 '18 at 11:41
33

This is by design. Facebook still have some issue with iOS9.

See the Facebook team answere : https://developers.facebook.com/bugs/786729821439894/?search_id Thanks

user3492452
  • 331
  • 2
  • 2
  • Correct - this is by design. After much testing and research, we've determined Safari View Controller offers a better and higher performing experience than fast-app-switching to the native FB app. – Simon Cross Oct 01 '15 at 15:40
  • 5
    @SimonCross this is kind of a bummer since many people aren't logged in via the browser (but app logins usually persist). – Callmeed Oct 05 '15 at 16:31
  • 1
    There's tens of millions of people already signed into Safari. And once someone is signed into Safari, they have really fast and lightweight FB Login experience without time for fast-app-switching via the popups, loading up the Facebook app and loading the web-rendered Login dialog within. – Simon Cross Oct 06 '15 at 15:21
  • 2
    @SimonCross this seems like some pretty poor research, then. I doubt very much that the vast majority of users are signed in on Safari. And those who aren't? Do they really remember their credentials? I'm guessing it's rather unlikely. – Josh Smith Oct 28 '15 at 22:33
  • 3
    @SimonCross all my friends don't use safari they use only facebook app to connect to Facebook and that logic.. Why as a developer we should force our user to connect via safari.. Many others use chrome but they don't care if safari is default browser in their phone – Hamza MHIRA Nov 11 '15 at 09:55
  • I'm testing on iOS9.1 and Iphone6+ and using FBSDKAppInviteDialog. The facebook web view that comes up is terrible. It's slow, unresponsive and I can't even select the first name in the invites list that appears... is this going to be fixed anytime soon? – techsMex Nov 13 '15 at 11:24
  • 1
    @SimonCross mind boggling how you came to that conclusion. Who uses safari, everyone is logged into the facebook app. Pain in the ass – DaynaJuliana Dec 01 '15 at 21:15
  • Login works fine. But, using "UIActivityViewController', Ii I share from my app, it's not taking authenticated logged in credentials. Its taking Phone FB logged in data. How to fix this! – Femina Dec 11 '15 at 11:17
11

In the end I changed my Podfile to previous FB version:
From:

pod 'FBSDKCoreKit' pod 'FBSDKLoginKit' pod 'FBSDKShareKit'
TO:

pod 'FBSDKCoreKit','~>4.5.1'
pod 'FBSDKLoginKit','~>4.5.1'
pod 'FBSDKShareKit','~>4.5.1'

From my point of view Facebook should check last login of the user and based on it trigger the correct Login flow.(and keep the small developers out of "web vs native war").

Mike.R
  • 2,824
  • 2
  • 26
  • 34
  • Extremely annoying that this was required, but thanks so much for providing this answer! Native app-switching is now working in iOS 9 for my app. – mdstroebel Feb 27 '16 at 12:12
  • This is the best answer. Wish I could vote it up a few times. Thank You. – edhnb Jun 22 '16 at 15:58
4

@dan is right. In order to provide the best experience for users on iOS 9, the new SDK determines the best login flow automatically. If you're running on iOS 8 or earlier, the app switch will still be preferred.

Chris Pan
  • 1,903
  • 14
  • 16
4

Safari View Controller is by default in the Facebook SDK. For those of you who want to revert to the previous experience, see below. It works only for 3.x SDK, this will not work on 4.x.

If you like to make the v3.x SDK (tested on v3.24.1) work like before (without opening Safari View Controller and make the app switch instead) call this code somewhere at the start of the app, e.g. didFinishLaunchingWithOptions:

SEL useSafariSel = sel_getUid("useSafariViewControllerForDialogName:");
SEL useNativeSel = sel_getUid("useNativeDialogForDialogName:");
Class FBDialogConfigClass = NSClassFromString(@"FBDialogConfig");

Method useSafariMethod = class_getClassMethod(FBDialogConfigClass, useSafariSel);
Method useNativeMethod = class_getClassMethod(FBDialogConfigClass, useNativeSel);

IMP returnNO = imp_implementationWithBlock(^BOOL(id me, id dialogName) {
    return NO;
});
method_setImplementation(useSafariMethod, returnNO);

IMP returnYES = imp_implementationWithBlock(^BOOL(id me, id dialogName) {
    return YES;
});
method_setImplementation(useNativeMethod, returnYES);

It swizzles two methods from FBDialogConfig.

Don't forget to import the objc/runtime.h header:

#import <objc/runtime.h>

@SimonCross some people just don't want to understand that Safari View Controller provides the best user experience - they think, or know for sure, that their users are not logged into Facebook in Safari, but are for sure logged in in the Facebook App.

Andrei Radulescu
  • 1,989
  • 1
  • 17
  • 29
  • I can't believe this change! I, for one, do not use Safari for anything. I have the Facebook and Facebook Messenger app but when I go to sign in with Facebook in third party apps I am taken to Safari and made to login manually through that!? – jakedunc Feb 10 '16 at 18:57
  • This is a great workaround answer! Tested it on iOS9, FB SDK 3.24.1 and it works as expected (opens FB Native App for login). – ckbhodge Mar 07 '16 at 09:24
  • Update: I'm seeing reports from users of my app with iOS 10.1+ failing to login now using this method. It's unclear from users where the issue occurs, but I'm likely going to need to disable this workaround now. – ckbhodge Nov 22 '16 at 08:40
3

After setting all the necessary .plist keys as mentioned in this column, I used following solution to come out of login problem.

var fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
fbLoginManager.loginBehavior = FBSDKLoginBehavior.Web

So that it always logs in with in application.

  • The beast answer! Thanks! – imike Feb 16 '16 at 21:22
  • This will work but it will get you rejected from the "Facebook App Review" process. They will tell you "Your app cannot embed the Facebook Login dialog inside a custom web view. Utilize our native Facebook Login SDK, so that users do not need to login twice." – snakeoil May 04 '16 at 02:19
2

With the release of iOS 9, Apple introduced some significant changes to app switching. This has affected iOS 9 apps integrated with Facebook. Most people will notice this in their experience using Facebook Login. In apps that use the newest SDK (v4.6 and v3.24), we will surface a flow using Safari View Controller (SVC) instead of fast-app-switching (FAS) because of additional dialog interstitials that add extra steps to the login process in FAS on iOS 9. Additionally, data that we've seen from more than 250 apps indicate that this is the best experience for people in the long run. Please read on for details. https://developers.facebook.com/blog/post/2015/10/29/Facebook-Login-iOS9

Venu Gopal Tewari
  • 5,672
  • 42
  • 41
2

Facebook has changed Facebook login behavior for iOS9.

Here is the quote from Facebook blog post:

We've been monitoring data and CTRs for over 250 apps over the last 6 weeks since iOS 9 launched. The click-through rate (CTR) of SVC Login outperforms the CTR of app-switch Login and is improving at 3x the rate of the app-switch experience. This indicates that the SVC experience is better for people and developers today, and will likely be the best solution in the long run. For this reason, the latest Facebook SDK for iOS uses SVC as the default experience for Login.

Haroun SMIDA
  • 1,106
  • 3
  • 16
  • 32
1

This worked for me. Add this to your .plist.

<key>LSApplicationQueriesSchemes</key>
    <array>
        <string>fb</string>
    </array>

For iOS9, we need to add key to our .plist for URL Schemes.

Sushil Sharma
  • 2,321
  • 3
  • 29
  • 49
  • can you let me know where you are adding this – Saty Nov 10 '15 at 09:57
  • I am adding this to my .plist. Right click on your .plist and open it as source code and this code there. – Sushil Sharma Nov 10 '15 at 10:04
  • I added however not working. my issue is my app does not open the native app that does not matter, I am opening the browser way however, I am not getting the data back where in iOS 8.4 I am getting data..that way – Saty Nov 10 '15 at 10:08
  • What data you want to retrieve ? Is there any error in log ? – Sushil Sharma Nov 10 '15 at 10:14
  • Actually Now iOS 9 is retrieving the data after I downloaded new sdks and included keys in info.plist and changed the code fbLoginManager .logInWithReadPermissions function now its not working in iOS 8.4 – Saty Nov 10 '15 at 10:39
  • Thats Good. Efforts never go waste. :) – Sushil Sharma Nov 10 '15 at 11:02
  • One of the issue I am finding that as I am suing Xcode 6.4 and FacebookSDKs-iOS-20151026.. now I can not run my app in iOS simulator. Its running on Devices. I found this http://stackoverflow.com/questions/32514962/linker-error-in-ios-duplicate-symbols-for-architecture-x86-64 issue as same as me however I can not upgrade my Xcode now and I have to support iOS 9 – Saty Nov 17 '15 at 05:25
  • I am using Latest FB SDK 4.6. FB Login, If I try CreateAccount, Its not redirecting back to my app. How to fix it? – Femina Dec 11 '15 at 11:15
1

I know it is old. But you can put this code to your application:(UIApplication *)application didFinishLaunchingWithOptions:

SEL useNativeSel = sel_getUid("useNativeDialogForDialogName:");
Class FBSDKServerConfiguration = NSClassFromString(@"FBSDKServerConfiguration");


Method useNativeMethod = class_getInstanceMethod(FBSDKServerConfiguration, useNativeSel);

IMP returnYES = imp_implementationWithBlock(^BOOL(id me, id dialogName) {
    return YES;
});
method_setImplementation(useNativeMethod, returnYES);

And FacebookSDK will login through native app when app installed instead of browser.

vien vu
  • 4,277
  • 2
  • 17
  • 30
0

Putting this one in appdelegate solved my problem

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
        return FBSDKApplicationDelegate.sharedInstance().application(app, open: url, sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String, annotation: options[UIApplicationOpenURLOptionsKey.annotation])
    }
Chanchal Raj
  • 4,176
  • 4
  • 39
  • 46
-3

Adding below lines to .plist file helped me:

<key>LSApplicationQueriesSchemes</key> 
    <array>
      <string>fbapi</string>
      <string>fbapi20130214</string>
      <string>fbapi20130410</string>
      <string>fbapi20130702</string>
      <string>fbapi20131010</string>
      <string>fbapi20131219</string>
      <string>fbapi20140410</string>
      <string>fbapi20140116</string>
      <string>fbapi20150313</string>
      <string>fbapi20150629</string>
      <string>fbauth</string>
      <string>fbauth2</string>
      <string>fb-messenger-api20140430</string>
    </array>
Cleb
  • 25,102
  • 20
  • 116
  • 151