基于Firebase平臺開發(四) —— Firebase基本使用簡介(二)

版本記錄

版本號 時間
V1.0 2019.02.01 星期五

前言

Firebase是一家實時后端數據庫創業公司,它能幫助開發者很快的寫出Web端和移動端的應用。自2014年10月Google收購Firebase以來,用戶可以在更方便地使用Firebase的同時,結合Google的云服務。Firebase能讓你的App從零到一。也就是說它可以幫助手機以及網頁應用的開發者輕松構建App。通過Firebase背后負載的框架就可以簡單地開發一個App,無需服務器以及基礎設施。接下來幾篇我們就一起看一下基于Firebase平臺的開發。感興趣的看下面幾篇文章。
1. 基于Firebase平臺開發(一) —— 基于ML Kit的iOS圖片中文字的識別(一)
2. 基于Firebase平臺開發(二) —— 基于ML Kit的iOS圖片中文字的識別(二)
3. 基于Firebase平臺開發(三) —— Firebase基本使用簡介(一)

Removing Items From the Table View

table view將同步對您的數據進行的任何類型的更改,但是當用戶決定不獲取該比薩餅時,現在無法更新Firebase。

要通知數據庫刪除,您需要設置Firebase引用以在用戶將其擦除時刪除項目。

找到tableView(_:commit:forRowAt :)。 現在,此方法使用索引路徑的行從本地數組中刪除雜貨項目。 它有效,但有更好的方法。 用以下內容替換現有實現:

if editingStyle == .delete {
  let groceryItem = items[indexPath.row]
  groceryItem.ref?.removeValue()
}

Firebase遵循單向數據流模型,因此viewDidLoad()中的偵聽器會向應用程序通知購物清單的最新值。 刪除項目會觸發值更改。

索引路徑的行用于檢索相應的雜貨項目。 每個GroceryItem都有一個名為refFirebase引用屬性,并且在該引用上調用removeValue()會導致您在viewDidLoad()中定義的偵聽器觸發。 偵聽器附加了一個閉包,它使用最新數據重新加載表視圖。

建立并運行。 滑動某個項目,點擊刪除,然后在您的應用和Firebase中觀看它消失。

干得好! 您的商品現在可以實時刪除。


Checking Off Items

現在你知道了如何添加,刪除和同步項目,這一切都非???。 但是當你真正購物時呢? 你應該刪除你已經擁有的東西,還是在將它們添加到你的購物籃時標記它們會更好?

點擊時,項目應變為灰色并顯示復選標記,以便向用戶提供一些不再需要該項目的視覺反饋。

打開GroceryListTableViewController.swift并找到toggleCellCheckbox(_:isCompleted :)。 此方法切換UITableViewCell的必要視圖屬性,具體取決于其關聯項是否完整。

首次加載表視圖時從tableView(_:cellForRowAtIndexPath :)調用它,當用戶點擊一行時從tableView(_:didSelectRowAt :)調用它。

用以下內容替換tableView(_:didSelectRowAt :)的當前實現:

// 1
guard let cell = tableView.cellForRow(at: indexPath) else { return }
// 2
let groceryItem = items[indexPath.row]
// 3
let toggledCompletion = !groceryItem.completed
// 4
toggleCellCheckbox(cell, isCompleted: toggledCompletion)
// 5
groceryItem.ref?.updateChildValues([
  "completed": toggledCompletion
])

下面就是詳細說明:

  • 1) 找到用戶使用cellForRow(at :)點擊的單元格。
  • 2) 使用索引路徑的行獲取相應的GroceryItem。
  • 3) 在grocery item上標記completed狀態。
  • 4) 調用toggleCellCheckbox(_:isCompleted :)來更新單元格的可視屬性。
  • 5) 使用updateChildValues(_ :),傳遞字典,以更新Firebase。 此方法與setValue(_ :)不同,因為它僅應用更新,而setValue(_ :)是破壞性的,并替換該引用處的整個值。

建立并運行。 點擊一個項目,看它在complete狀態和incomplete狀態之間來回切換。

恭喜你,你現在有了一個非常可愛的購物清單應用程序!


Sorting the Grocery List

如果選中的項目自動移動到列表的底部,則應用程序將更加強大10倍。 然后剩余的物品將清晰,易于您的眼睛看到。

使用Firebase queries,您可以按任意屬性對列表進行排序。 仍在GroceryListTableViewController.swift中工作,更新viewDidLoad()中的觀察者,如下所示:

ref.queryOrdered(byChild: "completed").observe(.value, with: { snapshot in
  var newItems: [GroceryItem] = []
  for child in snapshot.children {
    if let snapshot = child as? DataSnapshot,
       let groceryItem = GroceryItem(snapshot: snapshot) {
      newItems.append(groceryItem)
    }
  }
  
  self.items = newItems
  self.tableView.reloadData()
})

要按completed的值對數據進行排序,請在Firebase引用上調用queryOrdered(byChild :),該引用需要一個鍵才能按順序排序。

由于列表需要按completed順序排列,因此completedkey將傳遞給查詢。 然后,queryOrdered(byChild :)返回一個引用,通知服務器以有序的方式返回數據。

建立并運行。 點擊一行以切換其completion狀態。 完成的項目神奇地移動到列表的底部。

哇! 你真的在這里買雜貨。 看起來它應該足夠簡單,可以跨多個用戶同步數據,例如,與重要的其他用戶或室友同步。 這聽起來像......認證的工作!


Authenticating Users

Firebase具有身份驗證服務,允許應用程序通過多個providers進行身份驗證。 您可以使用Google,Twitter,Facebook,Github,電子郵件和密碼,匿名甚至自定義后端對用戶進行身份驗證。 在這里,您將使用電子郵件和密碼,因為它是最容易設置的。

要啟用電子郵件和密碼身份驗證,請轉到Firebase dashboard,然后單擊Authentication。

選擇SIGN-IN METHOD選項卡,然后在Sign-in providers部分中,選擇Email/Password行。 單擊Enable開關,然后單擊SAVE

Firebase將憑證存儲在鑰匙串中,因此最后一步是通過導航到目標Capabilities并切換鑰匙串共享來啟用Xcode中的Keychain Sharing

在Xcode提示時,選擇您的開發團隊。 這是必需的,因此Xcode可以為您管理簽名并自動啟用App ID的功能。
現在,您已準備好使用他們的電子郵件和密碼對用戶進行身份驗證!


Registering Users

LoginViewController.swift中,找到signUpDidTouch(_ :)。 這提供了一個允許用戶注冊帳戶的UIAlertController。 找到saveAction并將以下內容添加到其閉包中:

// 1
let emailField = alert.textFields![0]
let passwordField = alert.textFields![1]

// 2
Auth.auth().createUser(withEmail: emailField.text!, password: passwordField.text!) { user, error in
  if error == nil {
    // 3
    Auth.auth().signIn(withEmail: self.textFieldLoginEmail.text!,
                       password: self.textFieldLoginPassword.text!)
  }
}

下面進行詳細說明:

  • 1) 從alert controller獲取用戶提供的電子郵件和密碼。
  • 2) 在默認的Firebase auth對象上調用createUser(withEmail:password :),傳遞電子郵件和密碼。
  • 3) 如果沒有錯誤,則表示已創建用戶帳戶。 但是,您仍需要對此新用戶進行身份驗證,因此請調用signIn(withEmail:password :),再次傳遞提供的電子郵件和密碼。

建立并運行。 點擊Sign up按鈕并輸入電子郵件和密碼,然后點擊保存。 尚未成功登錄時,視圖控制器將無法導航到任何內容。 如果您刷新Firebase的Login & Auth標簽,您將看到新創建的用戶。

W00T!該應用程序現在注冊用戶,然后讓他們登錄。但是,不要慶祝,您需要完成該過程,以便人們可以按預期實際使用該應用程序。


Logging Users In

注冊按鈕可以注冊并登錄用戶。 但是,Login按鈕實際上無效,因為不執行身份驗證。

仍然在LoginViewController.swift中工作,找到loginDidTouch(_ :)并用以下內容替換它的實現:

guard
  let email = textFieldLoginEmail.text,
  let password = textFieldLoginPassword.text,
  email.count > 0,
  password.count > 0
  else {
    return
}

Auth.auth().signIn(withEmail: email, password: password) { user, error in
  if let error = error, user == nil {
    let alert = UIAlertController(title: "Sign In Failed",
                                  message: error.localizedDescription,
                                  preferredStyle: .alert)
    
    alert.addAction(UIAlertAction(title: "OK", style: .default))
    
    self.present(alert, animated: true, completion: nil)
  }
}

此代碼將在用戶嘗試通過點擊Login按鈕登錄時對用戶進行身份驗證。

現在,只有在用戶登錄時才需要將segue執行到下一個控制器。


Observing Authentication State

Firebase具有允許您監視用戶身份驗證狀態的觀察者。 這是一個執行segue的好地方。

將以下內容添加到LoginViewController

override func viewDidLoad() {
  super.viewDidLoad()
  
  // 1
  Auth.auth().addStateDidChangeListener() { auth, user in
    // 2
    if user != nil {
      // 3
      self.performSegue(withIdentifier: self.loginToList, sender: nil)
      self.textFieldLoginEmail.text = nil
      self.textFieldLoginPassword.text = nil
    }
  }
}

下面進行詳細說明:

  • 1) 使用addStateDidChangeListener(_ :)創建一個身份驗證觀察者。 該塊傳遞兩個參數:authuser。
  • 2) 測試user的值。 成功進行用戶身份驗證后,將為user填充用戶的信息。 如果身份驗證失敗,則變量為nil。
  • 3) 成功驗證后,執行segue并清除文本字段的文本。 你沒有將用戶傳遞給下一個控制器可能看起來很奇怪,但你會看到如何在GroceryListTableViewController.swift中獲取它。

1. Setting the User in the Grocery List

轉到GroceryListTableViewController.swift,并將以下內容添加到viewDidLoad()的底部:

Auth.auth().addStateDidChangeListener { auth, user in
  guard let user = user else { return }
  self.user = User(authData: user)
}

在此處,您將身份驗證觀察者附加到Firebase auth對象,該對象在用戶成功登錄時又會分配user屬性。

建立并運行。 如果用戶已登錄,則會繞過LoginViewController并轉到GroceryListTableViewController。 當用戶添加項目時,他們的電子郵件將顯示在單元格的詳細信息中。


Logging Users Out

由于用戶可以登錄,因此他們也應該能夠注銷。 打開OnlineUsers TableViewController.swift并用以下代碼替換signoutButtonPressed(_ :)中的代碼:

// 1
let user = Auth.auth().currentUser!
let onlineRef = Database.database().reference(withPath: "online/\(user.uid)")

// 2
onlineRef.removeValue { (error, _) in

  // 3
  if let error = error {
    print("Removing online failed: \(error)")
    return
  }

  // 4
  do {
    try Auth.auth().signOut()
    self.dismiss(animated: true, completion: nil)
  } catch (let error) {
    print("Auth sign out failed: \(error)")
  }
}

下面進行詳細說明:

  • 1) 首先獲取currentUser并使用其uid創建onlineRef,uid是表示用戶的唯一標識符。
  • 2) 您調用removeValue來刪除onlineRef的值。 Firebase會在登錄時自動將用戶添加到online,但在注銷時不會刪除用戶。 相反,它只會在用戶斷開連接時將其刪除。 對于此應用程序,在用戶注銷后將其顯示為online沒有意義,因此您可以在此處手動刪除它們。
  • 3) 在完成閉包中,首先檢查是否有錯誤,如果是這樣,只需打印它。
  • 4) 您在此處調用Auth.auth().signOut()以從鑰匙串中刪除用戶的憑據。 如果沒有錯誤,則關閉視圖控制器。 否則,您打印出錯誤。

構建并運行,點擊左側導航項,按Sign Out,您將返回登錄頁面。

成功! 該應用程序現在具有基本用戶身份驗證。


Monitoring Users’ Online Status

現在該應用程序具有用戶身份驗證,是時候檢測哪些用戶在線。 打開GroceryListTableViewController.swift并添加以下屬性:

let usersRef = Database.database().reference(withPath: "online")

這是Firebase參考,指向存儲在線用戶列表的在線位置。

接下來,將以下內容添加到viewDidLoad()內的addStateDidChangeListener(_ :)閉包的底部:

// 1
let currentUserRef = self.usersRef.child(self.user.uid)
// 2
currentUserRef.setValue(self.user.email)
// 3
currentUserRef.onDisconnectRemoveValue()

下面詳細分解:

  • 1) 使用用戶的uid創建子引用,該引用是在Firebase創建帳戶時生成的。
  • 2) 使用此參考來保存當前用戶的電子郵件。
  • 3) 在currentUserRef上調用onDisconnectRemoveValue()。 這會在與Firebase的連接關閉后刪除引用位置的值,例如當用戶退出您的應用時。 這非常適合監控已下線的用戶。

建立并運行。 加載視圖時,當前用戶的電子郵件將作為子項添加到在線位置。

很好! 現在是時候在用戶數量增加時更改條形按鈕項的數量了。

1. Updating the Online User Count

仍在GroceryListTableViewController.swift中,將以下代碼添加到viewDidLoad()

usersRef.observe(.value, with: { snapshot in
  if snapshot.exists() {
    self.userCountBarButtonItem?.title = snapshot.childrenCount.description
  } else {
    self.userCountBarButtonItem?.title = "0"
  }
})

這將創建一個用于監視在線用戶的觀察者。 當用戶上線和離線時,userCountBarButtonItem的標題將使用當前用戶計數進行更新。


Displaying a List of Online Users

打開OnlineUsersTableViewController.swift,就像之前一樣,在類的屬性部分中添加對Firebase的在線用戶記錄的本地引用:

let usersRef = Database.database().reference(withPath: "online")

viewDidLoad()中,替換:

currentUsers.append("hungry@person.food")

使用下面的代碼

// 1
usersRef.observe(.childAdded, with: { snap in
  // 2
  guard let email = snap.value as? String else { return }
  self.currentUsers.append(email)
  // 3
  let row = self.currentUsers.count - 1
  // 4
  let indexPath = IndexPath(row: row, section: 0)
  // 5
  self.tableView.insertRows(at: [indexPath], with: .top)
})

下面進行詳細分解:

  • 1) 創建一個偵聽添加到usersRef管理的位置的子節點的觀察者。 這與值偵聽器不同,因為只有添加的子節點傳遞給閉包。
  • 2) 從快照中獲取值,然后將其附加到本地陣列。
  • 3) 當前行始終是本地數組的計數減1,因為表視圖管理的索引是從零開始的。
  • 4) 使用計算的行索引創建實例NSIndexPath
  • 5) 使用動畫插入行,從而使單元格從頂部插入。

這只會在添加項目時呈現項目,而不是重新加載整個列表,它還使您能夠指定一個漂亮的動畫。

由于用戶可以脫機,因此表格也需要對被刪除的用戶做出反應。 在剛剛添加的代碼下面添加以下內容:

usersRef.observe(.childRemoved, with: { snap in
  guard let emailToFind = snap.value as? String else { return }
  for (index, email) in self.currentUsers.enumerated() {
    if email == emailToFind {
      let indexPath = IndexPath(row: index, section: 0)
      self.currentUsers.remove(at: index)
      self.tableView.deleteRows(at: [indexPath], with: .fade)
    }
  }
})

這只是添加了一個觀察者,它監聽被刪除的usersRef引用的子節點。 它在本地數組中搜索電子郵件值以查找相應的子項,一旦找到,它將從表中刪除關聯的行。

建立并運行。

Firebase用戶信息中心中點按Online,當前用戶的電子郵件將顯示在表格中。 使用一些技巧,可以將用戶添加到Online,一旦你這樣做,它就會顯示在列表中。 單擊儀表板中的Remove按鈕,用戶將消失。

添加和刪除用戶時,表會更新。


Enabling Offline

雜貨店以不穩定的數據連接而臭名昭著。 你認為他們現在都有Wi-Fi,沒有!

沒問題,您只需設置數據庫即可脫機工作。 打開AppDelegate.swift并將以下內容添加到application(_:didFinishLaunchingWithOptions:)return true之前:

Database.database().isPersistenceEnabled = true

是的,就是這樣! 就像您的應用程序脫機工作一樣。 一旦建立連接,即使跨應用重新啟動發生的離線更新也將應用于您的Firebase數據庫。

在整個Firebase教程中,您通過構建協作式購物清單應用程序了解了Firebase的基礎知識。 您已實施將數據保存到Firebase數據庫,實時同步數據,驗證用戶身份,監控在線用戶狀態以及啟用脫機支持。 而且你沒有編寫一行服務器代碼就完成了所有這些!

要了解有關Firebase的更多信息,請查看Firebase自己提供的文檔和示例(documentation)。

后記

本篇主要講述了Firebase基本使用簡介,感興趣的給個贊或者關注~~~

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容