版本记录
版本号 | 时间 |
---|---|
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
都有一个名为ref
的Firebase
引用属性,并且在该引用上调用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
顺序排列,因此completed
的key
将传递给查询。 然后,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(_ :)
创建一个身份验证观察者。 该块传递两个参数:auth
和user
。 - 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基本使用简介,感兴趣的给个赞或者关注~~~