基于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创建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基本使用简介,感兴趣的给个赞或者关注~~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容