【iOS】#10 訂飲料APP|Part.4 註冊、登入、設定使用者名稱 — Firebase Authentication
Published in
17 min readMar 21, 2024
前情提要 — 可不可飲料訂購APP為系列文章,初步規劃分為四篇文章介紹以下四大頁面及功能:
・註冊登入頁面:使用者註冊登入及訪客登入|Firebase 身份驗證
・Menu菜單頁面:串接 Airtable API 呈現飲料菜單|GET
・飲料訂購頁面:新增飲料訂單|POST
・訂購清單頁面:編輯、刪除訂單|PATCH、DELETE
本篇為註冊登入頁面
🌟 本篇重點功能
- 主頁設置、訪客登入、避免鍵盤遮擋內容
- Firebase 登入、登出
- Firebase 註冊、設定使用者名稱
功能介紹
(AutoLaout 畫面的程式碼較多,以下皆省略,完整程式碼可參考文章最後附上的 GitHub 連結)
① 主頁設置、訪客登入、避免鍵盤遮擋內容
1. 主頁設置
MainLoginViewController — 設置 UITextField
用於輸入訪客名稱
import UIKit
class MainLoginViewController: UIViewController {
// 訪客名稱輸入框
let guestLoginTextField = UITextField()
override func viewDidLoad() {
super.viewDidLoad()
// 設置UITextField的delegate為self
guestLoginTextField.delegate = self
}
}
// MARK: - UITextFieldDelegate方法
extension MainLoginViewController: UITextFieldDelegate {
// 用戶點擊Return鍵時被調用
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// 關閉鍵盤
textField.resignFirstResponder()
return true
}
}
MainLoginViewController — 設置 UIButton
用於訪客登入、顯示登入頁面、顯示註冊頁面
class MainLoginViewController: UIViewController {
// 訪客登入、帳密登入、註冊按鈕
let guestLoginButton = UIButton()
let loginButton = UIButton()
let registerButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
// 綁定按鈕功能
guestLoginButton.addTarget(self, action: #selector(guestLogin), for: .touchUpInside)
loginButton.addTarget(self, action: #selector(loginButtonTapped), for: .touchUpInside)
registerButton.addTarget(self, action: #selector(registerButtonTapped), for: .touchUpInside)
}
// 帳密登入
@objc func loginButtonTapped() {
let loginViewController = LoginViewController()
present(loginViewController, animated: true)
}
// 註冊
@objc func registerButtonTapped() {
let registerViewController = RegisterViewController()
present(registerViewController, animated: true)
}
}
2. 訪客登入功能
MainLoginViewController — guestLogin
用於訂單顯示訪客名稱
class MainLoginViewController: UIViewController {
// 錯誤訊息
let errorMessage = UILabel()
// 在訪客登入成功時調用,執行後續操作
var onLoginSuccess: ((String) -> Void)?
@objc func guestLogin() {
// 檢查訪客名稱不為空值
let userName = guestLoginTextField.text ?? ""
if userName == "" {
errorMessage.text = "請輸入訪客名稱" // 訪客名稱為空,顯示錯誤訊息
} else {
// 訪客登入成功時傳入訪客名稱
onLoginSuccess?(userName)
// 關閉視窗
self.dismiss(animated: true)
}
}
}
3. 避免鍵盤遮擋內容
RegisterViewController — Keyboard
使用文字輸入框時,避免鍵盤擋住螢幕 (畫面需搭配scrollView
)
(因註冊頁面文字輸入框較多,以註冊頁面為例)
class RegisterViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// 添加點擊手勢
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard))
view.addGestureRecognizer(tapGesture)
// 訂閱鍵盤彈出和隱藏的通知
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
deinit {
// 在視圖控制器銷毀時取消訂閱通知
NotificationCenter.default.removeObserver(self)
}
// 點擊手勢觸發
@objc func hideKeyboard() {
view.endEditing(true) // 收起所有正在編輯的元素的鍵盤
}
// 鍵盤彈出觸發
@objc func keyboardWillShow(_ notification: Notification) {
// 獲取鍵盤的高度
guard let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else {
return
}
// 設置 scrollView 的內容偏移量,使文本字段在鍵盤上方可見
scrollView.contentInset.bottom = keyboardSize.height
}
// 鍵盤隱藏觸發
@objc func keyboardWillHide(_ notification: Notification) {
// 隱藏鍵盤時重置 scrollView 的內容偏移量
scrollView.contentInset = .zero
}
}
② FireBase 登入、登出
1. FireBase 登入
LoginViewController — login
import FirebaseAuth
class LoginViewController: UIViewController {
@objc func login() {
// 獲取用戶輸入的帳號、密碼
let email = accountTextField.text!
let password = passwordTextField.text!
// Firebase登入
Auth.auth().signIn(withEmail: email, password: password) { result, error in
guard error == nil else {
// 登入失敗,顯示錯誤訊息
self.errorMessage.text = "\(error!.localizedDescription)"
return
}
// 登入成功,關閉視窗
self.dismiss(animated: true) {
NotificationCenter.default.post(name: Notification.Name("dismissMainLoginView"), object: nil)
}
}
}
}
2. FireBase 登出
MenuViewController — logout
class MenuViewController: UIViewController {
@objc func logout() {
// Firebase登出
do {
try Auth.auth().signOut()
} catch {
print(error)
}
}
}
③ FireBase 註冊、設定使用者名稱
1. FireBase 註冊
RegisterViewController — register
import FirebaseAuth
class RegisterViewController: UIViewController {
// 錯誤訊息
let errorMessage = UILabel()
// 註冊按鈕
let registerButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
// 綁定註冊按鈕功能
registerButton.addTarget(self, action: #selector(register), for: .touchUpInside)
}
@objc func register() {
// 獲取用戶輸入的帳號、密碼、暱稱
let email = accountTextField.text!
let password = passwordTextField.text!
let userName = userNameTextField.text
// 檢查暱稱不為空值
if userName == "" {
errorMessage.text = "請輸入您的暱稱" // 暱稱為空,顯示錯誤訊息
} else {
// Firebase註冊
Auth.auth().createUser(withEmail: email, password: password) { result, error in
guard let user = result?.user, error == nil else {
// 註冊失敗,顯示錯誤訊息
self.errorMessage.text = "\(error!.localizedDescription)"
return
}
// 註冊成功
print("success")
// 關閉視窗
self.dismiss(animated: true) {
NotificationCenter.default.post(name: Notification.Name("dismissMainLoginView"), object: nil)
}
}
}
}
}
2. FireBase 設定使用者名稱
RegisterViewController — register
import FirebaseAuth
class RegisterViewController: UIViewController {
@objc func register() {
// ...
// Firebase註冊
Auth.auth().createUser(withEmail: email, password: password) { result, error in
// 註冊失敗,顯示錯誤訊息...
// 註冊成功,設定使用者名稱(暱稱)
let changeRequest = Auth.auth().currentUser?.createProfileChangeRequest()
changeRequest?.displayName = userName
changeRequest?.commitChanges(completion: { error in
guard error == nil else {
// 設定使用者名稱失敗,顯示錯誤訊息
self.errorMessage.text = "\(error!.localizedDescription)"
return
}
// 設定使用者成功,註冊完成後關閉視窗
self.dismiss(animated: true) {
NotificationCenter.default.post(name: Notification.Name("dismissMainLoginView"), object: nil)
}
})
}
}
}
}
FireBase 取得使用者名稱
(以加入購物車功能為例)
@objc func addToCart() {
// 檢查是否為帳號登入,取得使用者名稱
if let user = Auth.auth().currentUser {
userName = user.displayName!
}
// 設置訂單內容、POST...
}
註冊、設定使用者名稱 — 完整程式碼
import FirebaseAuth
class RegisterViewController: UIViewController {
// 錯誤訊息
let errorMessage = UILabel()
// 註冊按鈕
let registerButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
// 綁定註冊按鈕功能
registerButton.addTarget(self, action: #selector(register), for: .touchUpInside)
}
@objc func register() {
// 獲取用戶輸入的帳號、密碼、暱稱
let email = accountTextField.text!
let password = passwordTextField.text!
let userName = userNameTextField.text
// 檢查暱稱不為空值
if userName == "" {
errorMessage.text = "請輸入您的暱稱" // 暱稱為空,顯示錯誤訊息
} else {
// Firebase註冊
Auth.auth().createUser(withEmail: email, password: password) { result, error in
guard let user = result?.user, error == nil else {
// 註冊失敗,顯示錯誤訊息
self.errorMessage.text = "\(error!.localizedDescription)"
return
}
// 註冊成功,設定使用者名稱(暱稱)
let changeRequest = Auth.auth().currentUser?.createProfileChangeRequest()
changeRequest?.displayName = userName
changeRequest?.commitChanges(completion: { error in
guard error == nil else {
// 設定使用者名稱失敗,顯示錯誤訊息
self.errorMessage.text = "\(error!.localizedDescription)"
return
}
// 設定使用者成功,註冊完成後關閉視窗
self.dismiss(animated: true) {
NotificationCenter.default.post(name: Notification.Name("dismissMainLoginView"), object: nil)
}
})
}
}
}
}