這一篇是繼續上一篇未完成的,請先看完這一篇:
這一篇就是程式碼的部份了,請確定你己經匯入好 Facebook SDK 與 Firebase SDK (Podfiel 中,應包括 Firebase/Core 與 Firebase/Auth),我們就可以開始了。
首先,是 AppDelegate.swift ,第一個動作是引入 SDK ,
import FBSDKLoginKit
Facebook 需要我們在這兒設兩個設定,第一個是在開啟時傳送選項在application(_:didFinishLaunchingWithOptions:) 加入
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
這是用來告訴 Facebook 的程式,APP啟動了,使用的選項是如同參數
另一個是要在 application(_:open:options:),預設專案 AppDelegate 不會設定這個方法,這個方法是用來設定 URL Scheme 有關,也就是說,告訴 APP 如何和 Facebook 溝通。整方法內容如下:
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { let handled: Bool = FBSDKApplicationDelegate.sharedInstance().application(app, open: url, sourceApplication: options[.sourceApplication] as? String, annotation: options[.annotation]) return handled }
然後,我們就可以設計 UI 了
畫面上有兩個物件,上面是 Facebook Login / Out Button,拉一個 UIView 然後把 Class 改為 FBSDKLoginButton 就可以了。 另一個是訊息,是一個標準的 UILabel。把這個 UI 物件 拉到 ViewContorller 中成為兩個 IBOutlet 我們就可以開始看 ViewController.swift 的程式了。
程式碼也很簡單,我們首先要對 Facebook Login Button 做兩個設定,第一個是把 delegate 設為 ViewController ,另一個是設定權限要求。在 ViewDidLoad 中 加入下面兩行就可以了。
facebookLoginButton.delegate = self facebookLoginButton.readPermissions = ["public_profile","email","user_friends"]
把 Delegate 設為 self 以便接收登入/登出時的時機,為了當 Delegate ,ViewController也要同時繼承 FBSDKLoginButtonDelegate 並新增兩兩方法,一個是登入完成的,另一個是登出的
先講登入完成的 loginButton(_ loginButton:, didCompleteWit result:, error:),在這個方法執行時,其實不定成功登入,也許會因為網路不通或使用者取消等原因而失敗,但若登入成功,則會回傳一個 FBSDKLoginManagerLoginResult 物件,其中就有我們需要的東西了。
成功登入 Facebook 後,就要利用登入資訊來登入到 Firebase 中。要作這件事,就要用 Firebase SDK 提供的 Auth 物件,這個物件是 Firebase 身份驗證的服務界面,登出登入查使用者都要用到它。取得它的實體很簡單,只要用 Auth.auth() 方法即可,然後.signIn(with: AuthCredential, completion:) 這個方法需要一個 AuthCredential,是一個登入的憑證,主要是如何存取 Facebook , 也就是用 Facebook 回傳的資料所產出的。
在 Facebook 回傳的 user 物件中,我們可以由 FBSDKAccessToken.current()?.tokenString 取得 存取 Facebook 令牌,有了個之後,就可以用 FacebookAuthProvider.credential 來產出 AuthCredential,我們就可以用它來登入 Firebase 了。
最後若是成功,就把顯示名稱秀出來。
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) { if error == nil{ if let accessToken = FBSDKAccessToken.current(){ let credential = FacebookAuthProvider.credential(withAccessToken: accessToken.tokenString) Auth.auth().signIn(with: credential, completion: { (user, error) in if error == nil{ if let user = Auth.auth().currentUser{ self.message.text = "歡迎:" + (user.displayName ?? "") let alertView = UIAlertController.init(title: "登入成功", message: "FB Sing in with:" + (user.email ?? ""), preferredStyle: UIAlertControllerStyle.alert) alertView.addAction(UIAlertAction.init(title: "OK", style: UIAlertActionStyle.default, handler: nil)) self.present(alertView, animated: true, completion: nil) } }else{ print(error?.localizedDescription) } }) } }else{ print(error.localizedDescription) } }
登出就比較簡單了,因為這是登出之後再回傳,所以不用檢查成功與否,秀訊息然後登出就可以了。
func loginButtonDidLogOut(_ loginButton: FBSDKLoginButton!) { message.text = "請登入" let alertView = UIAlertController.init(title: "登出", message: "FB Sing Out", preferredStyle: UIAlertControllerStyle.alert) alertView.addAction(UIAlertAction.init(title: "OK", style: UIAlertActionStyle.default, handler: nil)) self.present(alertView, animated: true, completion: nil) do { try Auth.auth().signOut() } catch { print(error.localizedDescription) } }
執行的畫面:
最後,到Firebase 的控制台,也能看到這個帳號,這個整合就算完成了。
AppDelegate.swift
import UIKit import Firebase import FBSDKLoginKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { FirebaseApp.configure() FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions) return true } func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool { let handled: Bool = FBSDKApplicationDelegate.sharedInstance().application(app, open: url, sourceApplication: options[.sourceApplication] as? String, annotation: options[.annotation]) return handled } }
ViewController.swift
import UIKit import FirebaseAuth import FBSDKLoginKit class ViewController: UIViewController,FBSDKLoginButtonDelegate { @IBOutlet weak var facebookLoginButton: FBSDKLoginButton! @IBOutlet weak var message: UILabel! override func viewDidLoad() { super.viewDidLoad() facebookLoginButton.delegate = self facebookLoginButton.readPermissions = ["public_profile","email","user_friends"] } //MARK:Facebook Login Button Delegate func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) { if error == nil{ if let accessToken = FBSDKAccessToken.current(){ let credential = FacebookAuthProvider.credential(withAccessToken: accessToken.tokenString) Auth.auth().signIn(with: credential, completion: { (user, error) in if error == nil{ if let user = Auth.auth().currentUser{ self.message.text = "歡迎:" + (user.displayName ?? "") let alertView = UIAlertController.init(title: "登入成功", message: "FB Sing in with:" + (user.email ?? ""), preferredStyle: UIAlertControllerStyle.alert) alertView.addAction(UIAlertAction.init(title: "OK", style: UIAlertActionStyle.default, handler: nil)) self.present(alertView, animated: true, completion: nil) } }else{ print(error?.localizedDescription) } }) } }else{ print(error.localizedDescription) } } func loginButtonDidLogOut(_ loginButton: FBSDKLoginButton!) { message.text = "請登入" let alertView = UIAlertController.init(title: "登出", message: "FB Sing Out", preferredStyle: UIAlertControllerStyle.alert) alertView.addAction(UIAlertAction.init(title: "OK", style: UIAlertActionStyle.default, handler: nil)) self.present(alertView, animated: true, completion: nil) do { try Auth.auth().signOut() } catch { print(error.localizedDescription) } } }