酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

iOSでFacebook SDKを使ってのログインに失敗する

先日「TwitterKitを使ってのログインで失敗する」という記事を書きました。Twitterにログインするだけのコードを書くのが随分と簡単になりました。

今日はFacebookにログインする処理を書いてみましたが、やはり少しハマってしまいました。導入ドキュメントを読んでないのがバレてしまう……

Facebook SDKを導入する

こちらも最近の流れに乗ってかCocoaPodsを使うだけで公式SDKが導入できてしまいます。Podfileに

pod 'FBSDKCoreKit'
pod 'FBSDKShareKit'
pod 'FBSDKLoginKit'

と書いてpod installでインストールします。

次に、Info.plistに下図のように定義を追加します。

f:id:ch3cooh393:20160327174051p:plain

SourceCodeモードで表示させると下記の通りです。

<key>FacebookAppID</key>
<string>xxxxxxxxxxxxxxx</string>
<key>FacebookDisplayName</key>
<string>$(PRODUCT_NAME)</string>
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>fbapi</string>
    <string>fb-messenger-api</string>
    <string>fbauth2</string>
    <string>fbshareextension</string>
</array>

最後に呼び元のアプリ(私が実装しているアプリ)に戻ってくるためにカスタムURLスキームを追加します。

f:id:ch3cooh393:20160327174217p:plain

ログイン処理は以下のように書くことができます。かなりシンプルで良い感じです。

func facebookLoginAction() {
    let login = FBSDKLoginManager()
    login.logInWithReadPermissions(["public_profile", "email"], 
        fromViewController: self) { (result: FBSDKLoginManagerLoginResult!, error: NSError!) in
        
        if error != nil {
            // 失敗!!
        } else if result.isCancelled {
            // キャンセル 
        } else {
            // 成功
        }
    }
}

logInWithReadPermissionsメソッドを実行するとiOS 8とiOS 9とで挙動が異なりますが、それぞれで正しくログインすることができませんでした。

ログインに失敗してしまう

iOSシミュレータを使ってのログインテストで、iOS 8.4、iOS 9のそれぞれで問題が発生することがわかりました。それぞれの現象について書きます。

iOS 8でログインができない!

iPhone 6/iOS 8のiOSシミュレータでログインのテストをしてみました。iOS 8ではlogInWithReadPermissionsメソッドを実行するとブラウザが起動します。

IDとパスワードを入力してログインに成功して、アプリ連携を許可するを選択すると、呼び元のアプリに戻るのですが、result.isCancelledの値が常にtrueになってしまいます。

エラーは発生していない(NSErrorはnilになっていてエラー情報を持たない)のですが、アクセストークンは取得できずユーザーによるキャンセル状態になってしまいます。

iOS 9でログインができない!

iPhone 6s/iOS 9のiOSシミュレータでログインのテストをしてみました。iOS 9ではlogInWithReadPermissionsメソッドを実行するとSFSafariViewControllerを使った画面遷移がおこなわれます。

SFSafariViewController上でIDとパスワードを入力してログインに成功して、アプリ連携を許可するを選択しても呼び出し元のアプリに戻ってくれませんでした。logInWithReadPermissionsメソッドで指定しているクロージャも呼ばれていない状態です。

解決策

両方ともAppDelegateにFacebook SDKのための実装をしていなかったのが原因で問題が発生していました。

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    
    FBSDKSettings.setAppID("xxxxxxxxxxxxxx")

    return 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)
}

これで前述した問題は発生しなくなり正しくログイン処理がおこなわれるようになりました。

関連記事

この他にもiOSアプリ開発で見つけたネタや悩んだ内容など紹介しています。Tipsをまとめておりますのでこちらのページをご参照ください。