模仿 Music App +實作 Table View 的基本功能+FireBase登入認證 — （3） Facebook 登入
By: Andy Lin
Tags: iOS, Facebook, Swift, Firebase

貼上完後 ,大致如下圖 . 可以發現裡面帶有管理Facebook登入需要的內容, 比如 CFBundleURLSchemes 就是前幾篇提到的 URL Types 中需要的URL Schemes欄

Facebook用ApplicationDelegate的application方法處理facebook登入資訊

在 參數 didFinishLaunchingWithOptions的方法中，使用 ApplicationDelegate.shared.application(application,

didFinishLaunchingWithOptions: launchOptions)來設置/初始化Facebook登入功能

由於iOS 是由參數open URL的方法來做判斷要前往哪一個URL Scheme，因此藉由url.absoluteString.contains(“”)來判斷是那一個Scheme，讓iOS App可以進行切換

import UIKit

import Firebase

import GoogleSignIn

import FacebookCore

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

// 設置/初始化Firebase

FirebaseApp.configure()

// 設置/初始化GoogleSignIn



GIDSignIn.sharedInstance()?.clientID = FirebaseApp.app()?.options.clientID // 設置/初始化Facebook登入功能



ApplicationDelegate.shared.application(application,

didFinishLaunchingWithOptions: launchOptions)

return true

} func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {

var handled:Bool = true



if url.absoluteString.contains("google"){

handled = GIDSignIn.sharedInstance().handle(url)

}else if url.absoluteString.contains("fb"){

handled =

ApplicationDelegate.shared.application(app, open: url,options:

options)

}

return handled }

如果 APP 是 iOS 13 以後的版本，還要在 SceneDelegate import FacebookCore, 並且加入下列程式碼。

import UIKit

import FacebookCore

func scene(_ scene:UIScene, openURLContexts URLContexts:Set<UIOpenURLContext>) {

guard let url = URLContexts.first?.url else { return }

ApplicationDelegate.shared.application( UIApplication.shared, open: url, sourceApplication: nil, annotation: [UIApplication.OpenURLOptionsKey.annotation] )

}

接下來說明登入畫面上的FB按鈕操作

如果是由自己拉 @IBAction 設定按鈕

那一定要呼叫LoginManager , 詳請原因可以參考Peter 的文章

不過我做的方式比較偷懶一點，就像GoogleSignIn 有提供GIDSignInButton 這個 UI 設定 Facebook 也有提供

還記得我們有引入FacebookLogin這個SDK 嗎？,這時候就能import並且生成 FB提供的FBLoginButton這個UI.

而因為是程式碼設立UI, 因此這裡設立一個CGPoint 接著將Button加入view中。

設立好UI之後, 我們要設定按完Facebook 登入按鈕要做甚麼事, 這時要遵從LoginButtonDelegate這個Protocol .這個Protocol 裡面有loginButton以及loginButtonDidLogOut 方法 , 它們處理登入及登出要做事情

然後透過permissions設定好fB App 開放的權限

class SignInViewController: UIViewController,LoginButtonDelegate{ override func viewDidLoad() {

super.viewDidLoad()

loginButton.delegate = self

loginButton.permissions = ["public_profile ","email"]

} func loginButton(_ loginButton: FBLoginButton, didCompleteWith result: LoginManagerLoginResult?, error: Error?) { } func loginButtonDidLogOut(_ loginButton: FBLoginButton) {

print(“log out”) }

}

}

記得將Firebase 認證的程式碼 寫在loginButton這個方法裡面 , 很重要, 很重要, 很重要 說三次 因為沒寫在此方法裡面,就跑不出憑證

//處理 Facebook 登入

func loginButton(_ loginButton: FBLoginButton, didCompleteWith result: LoginManagerLoginResult?, error: Error?) {

guard let token = AccessToken.current,!token.isExpired else{

return }

let credential = FacebookAuthProvider.credential(withAccessToken: token.tokenString)

Auth.auth().signIn(with: credential) { (fbUser, error) in

guard error == nil else{

return print(error!.localizedDescription)

} //...

}

}

而要做Firebase Auth 的Facebook憑證程式碼 與Google 憑證大同小異

差別只在Facebook憑證的內容是寫在 AccessToken.current裡面, 而操作憑證的物件由GoogleAuthProvider改為FacebookAuthProvider

let token = AccessToken.current

let credential = FacebookAuthProvider.credential(withAccessToken: token.tokenString)

上述段落的完整程式碼

import UIKit

import FacebookLogin class SignInViewController: UIViewController,LoginButtonDelegate{

override func viewDidLoad() {

super.viewDidLoad()

let loginButton = FBLoginButton()

loginButton.frame.origin = CGPoint(x: 90, y: 450)

view.addSubview(loginButton)

loginButton.delegate = self

loginButton.permissions = ["public_profile ","email"] }



//處理 Facebook 登入

func loginButton(_ loginButton: FBLoginButton, didCompleteWith result: LoginManagerLoginResult?, error: Error?) {

guard let token = AccessToken.current,!token.isExpired else{

return }

let credential = FacebookAuthProvider.credential(withAccessToken: token.tokenString)

Auth.auth().signIn(with: credential) { (fbUser, error) in

guard error == nil else{

return print(error!.localizedDescription)

} //...

}

}



func loginButtonDidLogOut(_ loginButton: FBLoginButton) {

print("log out") }

}

最後因為我們的 App 目前是開發者模式，所以不能直接用自己的 Facebook 帳號來登入。如果沒有另外的Facebook帳號，可以至角色 — 測試帳戶來進行申請，新增完後可以將fB 隨機產生帳戶的密碼改成自己能記得的密碼