iT邦幫忙

2021 iThome 鐵人賽

DAY 20
0
Mobile Development

在 iOS 開發路上的大小事系列 第 20

【在 iOS 開發路上的大小事-Day20】透過 Firebase 來管理使用者 (Sign in with Facebook 篇) Part2

  • 分享至 

  • xImage
  •  

昨天我們已經完成了 Sign in with Facebook 的前置作業了,今天我們要來將功能實作出來

畫面設計

我們先在 Storyboard/Xib 上拉出一個 UIButton

程式實作

在要實作 Sign in with Facebook 功能的 Controller 引入下面兩個

import FirebaseAuth
import FBSDKLoginKit

元件的 IBOutlet 如下

@IBOutlet weak var signInWithFacebookBtn: UIButton!

宣告一個 isSign 變數,型別為 Bool,用來判斷是否已經登入
然後在宣告一個 loginManager 常數,讓他等於 LoginManager(),用來進行登入/登出

var isSign: Bool = false // 預設為尚未登入
let loginManager = LoginManager()

接著在登入按鈕的 IBAction 加入下面的程式碼

@IBAction func signInWithFacebook(sender: UIButton) {
    if (self.isSign) {
        self.facebookAccountSignOut() // 已經登入的話,按下按鈕會執行登出功能
    } else {
        self.signInWithFacebook() // 尚未登入的話,按下按鈕會執行登入功能
    }
}

按下按鈕登入成功後,Facebook 會回傳使用者的 accessToken
接著就可以用 FacebookAuthProivder.credential() 這個 method 來產生該使用者的憑證
後面就可以透過這個憑證來與 Firebase 串接在一起了

extension SignInWithFacebookVC {
    // MARK: - Firebase Sign in with Facebook
    // 登入帳號
    func signInWithFacebook() {
        loginManager.logIn(permissions: ["email"], from: self) { loginResult, error in
            guard error == nil else {
                CustomFunc.customAlert(title: "", message: "\(String(describing: error!.localizedDescription))", vc: self, actionHandler: nil)
                return
            }
            guard ((loginResult?.isCancelled) != nil) else {
                CustomFunc.customAlert(title: "Facebook 登入失敗!", message: "", vc: self, actionHandler: nil)
                return
            }
            guard let accessToken = AccessToken.current else {
                CustomFunc.customAlert(title: "無法取得 AccessToken!", message: "", vc: self, actionHandler: nil)
                return
            }
            let credential = FacebookAuthProvider.credential(withAccessToken: accessToken.tokenString)
            self.firebaseSignInWithFacebook(credential: credential)
        }
    }
    
    func firebaseSignInWithFacebook(credential: AuthCredential) {
        Auth.auth().signIn(with: credential) { authResult, error in
            guard error == nil else {
                CustomFunc.customAlert(title: "", message: "\(String(describing: error!.localizedDescription))", vc: self, actionHandler: nil)
                return
            }
            CustomFunc.customAlert(title: "登入成功!", message: "", vc: self, actionHandler: self.getFirebaseUserInfo)
            self.signInWithFacebookBtn.setTitle("Facebook Account Sign Out", for: .normal)
            self.isSignIn = true
        }
    }
    
    // 登出帳號
    func facebookAccountSignOut() {
        do {
            try Auth.auth().signOut()
            loginManager.logOut()
            CustomFunc.customAlert(title: "帳號已登出!", message: "", vc: self, actionHandler: nil)
            self.signInWithFacebookBtn.setTitle("Connect with Facebook", for: .normal)
            self.isSignIn = false
        } catch let error as NSError {
            CustomFunc.customAlert(title: "", message: "\(String(describing: error.localizedDescription))", vc: self, actionHandler: nil)
        }
    }
}

如果要判斷目前是否已經有使用者登入了,可以在 viewWillAppear 加入判斷

// MARK: - 加入 Firebase 帳號狀態監聽
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    if let token = AccessToken.current, !token.isExpired {
        CustomFunc.customAlert(title: "帳號已登入過!", message: "", vc: self, actionHandler: self.getFirebaseUserInfo)
        self.signInWithFacebookBtn.setTitle("Sign Out", for: .normal)
        self.isSignIn = true
    } else {
        // 目前尚無用戶登入
        print("目前尚無用戶登入!")
    }
}

要讀取目前登入使用者的資料,可以這樣來讀取

// MARK: - Firebase 取得登入使用者的資訊
func getFirebaseUserInfo() {
    let currentUser = Auth.auth().currentUser
    guard let user = currentUser else {
        CustomFunc.customAlert(title: "使用者資訊", message: "無法取得使用者資料", vc: self, actionHandler: nil)
        return
    }
    let uid = user.uid
    let email = user.email
    let name = user.displayName
    CustomFunc.customAlert(title: "使用者資訊", message: "User Name:\(name!)\nUID:\(uid)\nEmail:\(email!)", vc: self, actionHandler: nil)
}

成果

Yes

本篇的範例程式碼:Github


上一篇
【在 iOS 開發路上的大小事-Day19】透過 Firebase 來管理使用者 (Sign in with Facebook 篇) Part1
下一篇
【在 iOS 開發路上的大小事-Day21】透過 Firebase 來管理使用者 (Sign in with Apple 篇) Part1
系列文
在 iOS 開發路上的大小事30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言