美文网首页js css html
基于Firebase平台开发(四) —— Firebase基本使

基于Firebase平台开发(四) —— Firebase基本使

作者: 刀客传奇 | 来源:发表于2019-02-01 14:25 被阅读44次

    版本记录

    版本号 时间
    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创建onlineRefuid是表示用户的唯一标识符。
    • 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基本使用简介,感兴趣的给个赞或者关注~~~

    相关文章

      网友评论

        本文标题:基于Firebase平台开发(四) —— Firebase基本使

        本文链接:https://www.haomeiwen.com/subject/pfnrsqtx.html