Firebase Tutorial: Getting Started 教程翻译

备注: 本教程已由 Attila Hegedüs 更新适配 iOS 10 和 Swift 3,原教程由David East 创作。
原文:https://www.raywenderlich.com/139322/firebase-tutorial-getting-started-2
翻译:JoeyChang 转载请标明出处

原文:http://www.jianshu.com/p/c61d118c216c

Firebase 是一个移动后台服务,它可以帮助我们创建具有优秀特性的移动 apps。Firebase 提供以下三个主要服务: a realtime database, user authentication and hosting。通过集成 Firebase iOS SDK, 你几乎不用写一行代码就能创建出非常棒的应用。

Firebase 具有数据库实时性这样的独特性能。

你曾经使用过 pull-to-refresh 去拉新数据么?有了 Firebase,现在你可以忽略那种刷新数据方法了。

当 Firebase 数据库更新时,所有的连接者可以实时获取更新,这就意味着你的 app 可以不用用户交互就能获取数据库当前最新值。

本篇 Firebase 教程中,我们将通过创建一个名叫 Grocr 的具有协作性的grocery list app , 来学习Firebase 的一些基本原理。当我们添加一个项目到列表时,它将实时出现在用户的其它设备中,但是我们并不满足于此,我们还将调整 Grocr 让它可以离线工作,以致即使仅有一个 grocery 数据连接,列表也能保持同步。

通过本文,你将学习到以下技能:
* 保存数据到Firebase数据库
* 从 Firebase 实时同步数据
* 验证 users
* 在线监控 users
* 实现离线支持

开始,下载初始项目 Grocr-starter. 它使用 CocoaPods 管理 Firebase 。

在 Xcode 中打开 Grocr.xcworkspace,该项目包含三个view controllers:
1. LoginViewController.swift.
现在登录功能还是使用的硬编码 user credentials,稍后我们将优化它。

  1. GroceryListTableViewController.swift.
    这个 controller 是 UITableViewController 子类,它通过 UIAlertController 添加 items 到本地数据库的 list 表格。

  2. OnlineUsersTableViewController.swift.
    该 controller 使用 Firebase’s presence feature 展示所有当前在线 users。

此外,还有两个模型类 GroceryItem.swiftUser.swift 。它们做为 app 的数据模型。

Build and run, 你将看到如下这样效果:

Grocr-Starter

注: 当 build 工程时,我们将看到一些 ‘nullability’ 编译警告。它们来自Firebase,暂时我们先忽略它们,稍后解决。

我们可以点击 Login 进行登录,这将使用一个写死的 user 数据,现在该 app 还只能使用本地数据。接下来我们将调用 Firebase 数据使 app 生动起来。

创建 Firebase 账号

有两个重要步骤:
1. 创建免费 Firebase 账号
2. 获取你第一个 app 的 URL

我们可以访问 Getting Started page 进行注册。当我们使用我们谷歌账号共享登录进入 firebase, 我们将看到一个干净的 Firebase 控制台。不要担心费用问题,现在 Firebase 免费版本已经足够强大,够用了。

01-firebase-welcome
创建我们的第一个工程,点击 CREATE NEW PROJECT 。在弹出的对话框中输入项目名称以及你的首选 国家/地区:

02-firebase-create-project

点击 CREATE PROJECT, 我们就可以通过控制面板来管理我们的项目了。

03-firebase-dashboard

这将作为所有 Firebase 服务的容器,我们用它存储数据和授权用户。
选择 Add Firebase to your iOS app 开始我们的项目。本项目的 bundle ID 是 rw.firebase.gettingstarted,所以添加此 id 到 iOS bundle ID 文本框。

04-firebase-add-ios-app-1

点击 ADD APP ,将下载一个 GoogleService-Info.plist 文件。将该文件拖拽到 Xcode 中的 Grocr 项目。

04-firebase-add-ios-app-2

点击 CONTINUE. 接下来一页描述怎样安装 Firebase SDK。

04-firebase-add-ios-app-3

本项目已经替我们集成好了,所以点击 CONTINUE 继续。最后一页说明当 app 启动时怎样连接到 Firebase。

04-firebase-add-ios-app-4

点击 FINISH ,查看新项目细节。

04-firebase-add-ios-app-5

Xcode 打开 GroceryListTableViewController.swift ,添加如下代码,创建 Firebase 连接。

let ref = FIRDatabase.database().reference(withPath: "grocery-items")

这个 Firebase 连接使用已提供的 path。在 documentation 中,这些 Firebase 属性被称为 references ,它们指定 Firebase 的位置。

简言之,这些属性可以实现保存和同步数据到给定的位置。

我们发现,base URL 不是必须的,相反,它使用 grocery-items 的 child path。Firebase 数据库是 JSON NoSQL 数据库,所以数据都是保存为 JSON 格式。

JSON 是分等级的 key-value 数据结构 – keys 指的是可以根据它获取其它对象格式的 values 值。JSON data 是一个简单的 key value 对儿树形结构。

在 Firebase 中,key 是一个 URL,value是形如 number, string, boolean , object 的随意的数据。

Structuring Data

无论客户端是什么数据格式,保存到 Firebase 的是 JSON 格式。下面是一个 JSON 示例:

// The root of the tree
{ // grocery-items 
    "grocery-items": { 
         // grocery-items/milk 
          "milk": {
                // grocery-items/milk/name 
               "name": "Milk", 

               // grocery-items/milk/addedByUser 
              "addedByUser": "David" 
          },
         "pizza": { 
               "name": "Pizza",
                "addedByUser": "Alice"
          }, 
   }
}

在上面的 JSON 中,你可以看到每对儿数据都是以键值对儿形式出现的。我们可以继续遍历树并在更深的位置检索数据。

在上面的例子中,我们可以通过路径检索所有的 grocery item。

grocery-items

如果你想获取第一个 grocery item ,你可以通过以下路径获取:

grocery-items/milk

因为所有的 Firebase keys 对应paths,所以 key 的名字选择很重要。

Understanding Firebase References

一个基本的原则是,Firebase 引用指向 Firebase 中数据存储的位置。如果我们创建多引用,那么这些引用共享同一个连接。
看如下代码:

// 1
let rootRef = FIRDatabase.database().reference()

// 2
let childRef = FIRDatabase.database().reference(withPath: "grocery-items")

// 3
let itemsRef = rootRef.child("grocery-items")

// 4
let milkRef = itemsRef.child("milk")

// 5
print(rootRef.key)   // prints: ""
print(childRef.key)  // prints: "grocery-items"
print(itemsRef.key)  // prints: "grocery-items"
print(milkRef.key)   // prints: "milk"

下面我们解释下:
1. 我们创建一个到 Firebase 数据库 root 引用。
2. 使用一个 URL ,我们可以创建一个引用到 Firebase 数据库的子路径。
3. 通过给 rootRef 传递子路径,我们可以使用 child(_:) 创建子引用,这个引用和上面的引用是一样意思。
4. 使用 itemsRef ,我们可以创建到 milk 的子引用。
5. 每个引用都有 key 属性。这个属性和 Firebase 数据库关键字的名字一样。

我们不需要在同一个项目中都添加这样的代码,这里只是出于展示目的进行列举。

Adding New Items to the List

GroceryListTableViewController.swift 的底部,找到 addButtonDidTouch(_:) 方法。

在这里我们要实现通过 UIAlertController 的方式添加一个新的 item 。

在 saveAction 方法内,现在仅仅保存数据到一个本地 array,因此 saveAction 不能同步不同客户端的数据,而且在下次启动 app 时,保存的数据将丢失。

没有人会使用不能记录或者同步他们 grocery 清单数据的 app ! 让我们完善 saveAction 方法:

let saveAction = UIAlertAction(title: "Save",
                               style: .default) { _ in
    // 1
    guard let textField = alert.textFields?.first,
      let text = textField.text else { return }

    // 2
    let groceryItem = GroceryItem(name: text,
                           addedByUser: self.user.email,
                             completed: false)
    // 3
    let groceryItemRef = self.ref.child(text.lowercased())

    // 4
    groceryItemRef.setValue(groceryItem.toAnyObject())
}

注释如下:
1. 从 alert controller 获取 text field 和它的内容。

  1. 使用当前用户数据创建一个新的 GroceryItem 。

  2. 使用 child(_:) 创建一个子引用,这个引用的 key 是 item 的小写名称,因此如果我们添加一个复制的 item (即使使用大写字母,或者使用混合字母),数据库只保存最后一个。

  3. 使用 setValue(_:) 保存数据到数据库。这个方法期望一个字典格式。GroceryItem 有个 toAnyObject() 方法,可以转换对象为字典格式。

在你可以连接数据库之前,我们还需要配置它。找到 AppDelegate.swift ,并在 application(_:didFinishLaunchingWithOptions:) 返回 true 之前添加如下代码:

FIRApp.configure()

默认情况,Firebase 数据库需要用户授权读写权限。在浏览器进入 Firebase 控制面板,选中左边的 Database 选项,设置 RULES 如下:

firebase-db-rules

{
  "rules": {
    ".read": true,
    ".write": true
  }
}

修改后,选择 PUBLISH 按钮进行保存设置。
Build and run. 在 Firebase 控制面板,选择 DATA 标签,并将浏览器窗口紧挨模拟器。当我们在模拟器中添加 item ,我们将看到它会出现在控制面板。

fb-save

现在,我们就有了一个可以实时添加数据到 Firebase 的活生生的 grocery list app!但是虽然 key 特性已经可以运行完好了,但是没有数据添加到table view。

那么我们怎样才能将数据从数据库同步到 table view 呢?

Retrieving Data

我们可以通过 observeEventType(_:withBlock:) 方法异步检索 Firebase 中的数据。

GroceryListTableViewController.swift 的 viewDidLoad() 下添加如下方法:

ref.observe(.value, with: { snapshot in
  print(snapshot.value)
})

该方法有两个参数:FIRDataEventType 的一个实例以及一个闭包。

event type 确定我们要监听的事件,.value 监听诸如 add, removed, changed 这样的 Firebase 数据库重点数据改变。

当改变发生,数据库使用最新数据更新 app 显示。

app 在闭包方法中通过接受到的 FIRDataSnapshot 一个实例获知数据改变。snapshot,代表某个特定时间点的数据快照。我们可以通过 value 那个属性获取到 snapshot 的数据。

Build and run,我们将看到,在控制台会有 items 列表数据被打印出来。

Optional({
    pizza =     {
        addedByUser = "hungry@person.food";
        completed = 0;
        name = Pizza;
    };
})
Synchronizing Data to the Table View

注意打印日志–现在在 table view 中可以看到 grocery 列表了。

GroceryListTableViewController.swift, 替换之前的代码片段为如下代码:

// 1
ref.observe(.value, with: { snapshot in
  // 2
  var newItems: [GroceryItem] = []

  // 3
  for item in snapshot.children {
    // 4
    let groceryItem = GroceryItem(snapshot: item as! FIRDataSnapshot)
    newItems.append(groceryItem)
  }

  // 5
  self.items = newItems
  self.tableView.reloadData()
})

以上代码的诸行解释:

  1. 添加一个监听器监听 grocery-items 改变了什么。

  2. 存储最近一次版本数据到闭包中本地的一个变量中。

  3. 监听者闭包返回最近数据的一个 snapshot,这个 snapshot 包含所有的 grocery items,而不是仅仅包含改变的 items。使 snapshot.children ,我们可以循环获取 grocery items 。

  4. GroceryItem 结构有一个常用的实例化器,它使用 FIRDataSnapshot
    来填充它的属性。snapshot 的值可以为任意类型,可以是 dictionary, array, number, or string。当创建好一个 GroceryItem 实例,它被添加到一个包含最近一次版本数据的数组中。

  5. 将最新版本的数据赋值给 items,然后更新 table view,使它展示最新数据。
    Build and run. 添加一个 pizza item 怎么样? 它将显示到 table view。

fb-sync
不用刷新,就可以及时获取到更新后的数据。

realtime-updates

Removing Items From the Table View

table view 将同步我们所有的改变数据, 但是当我们想删除 pizza 时,现在还不能更新。

为了通知数据库删除数据,我们需要设置一个 Firebase reference,当用户轻扫时候删除 item。

定位到 tableView(_:commit:forRowAt:)。现在,该方法使用 index 移除 array 中的 grocery item。这可以实现功能,但我们还有更好的解决方法。替换为如下实现方式:

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
  if editingStyle == .delete {
    let groceryItem = items[indexPath.row]
    groceryItem.ref?.removeValue()
  }
}

Firebase 遵从单向数据流模型,因此 viewDidLoad() 的 listener 监听 grocery list 的最新数据。清除 item 触发数据改变。

index path 的 row 被用来获取相关的 grocery item。每个 GroceryItem 拥有一个名为 ref 的 Firebase reference property,调用 它的 removeValue() 将移除我们在 viewDidLoad() 定义的 listener。该listener有一个闭包,它使用最新的数据重新加载表视图。

Build and run. 轻扫 item ,点击删除,我们发现 app 和 Firebase 的数据都消失了。

fb-delete

Nice work! 我们 items 可以实时删除了。

Checking Off Items

现在我们知道了怎么添加、删除以及同步 items ,这很酷。但是当我们实际购物时候会怎样呢?我们会删除我们刚购买的物品么,或者当我们添加购物车时给物品打个标记是否更好?

在以前的纸质时代,人们过去常常把东西从购物清单上划掉,因为我们也将在我们的 app 用现代的方式模仿这个行为。

grocery-list

打开 GroceryListTableViewController.swift ,找到 toggleCellCheckbox(_:isCompleted:) 方法,该方法可以根据 item 是否完成来切换UITableViewCell 的必要视图属性。

当 table view 第一次加载后,刚方法在tableView (_:cellForRowAtIndexPath:) 中会被调用,以及当用户点击 cell 时也会被调用。

替换 tableView(_:didSelectRowAt:) 方法为如下:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  // 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:) 确定用户点击的 cell。
2. 根据 index path 的 row 获取对应的 GroceryItem。
3. 改变 grocery item 的 completed 的状态。
4. 调用 toggleCellCheckbox(_:isCompleted:) 更新 cell 的属性。
5. 在 updateChildValues(:) 方法中,通过传递字典参数,更新Firebase。该方法与 setValue(:) 不同,因为它只应用更新,而setValue(_:) 具有破坏性,并在该引用中替换整个值。

Build and run. 点击一个 item,我们就可以看到该行被勾号标记并排序。

fb-toggle
恭喜,我们已经完成了一个相当漂亮的 grocery list app 。

Sorting the Grocery List

如果把 ice cream 放在未排序的标记里面,有时我们可能会忘记它。现在让我们进行些优化。

如果可以把已选中的 items 自动移动到列表底部,我们的 app 将更加令人喜欢。这样,未被标记的 items 可以更容易被我们发现。

使用 Firebase queries, 我们可以根据任意属性对列表进行排序,在GroceryListTableViewController.swift, 更新 viewDidLoad() 方法:

ref.queryOrdered(byChild: "completed").observe(.value, with: { snapshot in
  var newItems: [GroceryItem] = []

  for item in snapshot.children {
    let groceryItem = GroceryItem(snapshot: item as! FIRDataSnapshot)
    newItems.append(groceryItem)
  }

  self.items = newItems
  self.tableView.reloadData()
})

通过关键词 “ completed”,使用 Firebase 引用 queryOrdered(byChild:) 对数据进行排序。

由于列表需要完成顺序,所以 completed 键将传递给查询。然后,queryOrdered(byChild:)返回一个引用,通知服务器以有序的方式返回数据。

Build and run. 点击一行,使其置换为已完成状态,我们将看到,它神奇地自动移动到了最后一行。

fb-order

哇! 我们现在真的让购物变得更容易了。跨多个用户同步数据,似乎应该足够简单,例如,与一个重要的其他用户或 housemate。这听起来像…身份验证!

Authenticating Users

Firebase 有一个 authentication service,它允许 apps 验证不同的提供者,我们可以使用 Google, Twitter, Facebook, Github, email & password, 匿名, 甚至 custom backends 这些方式。这里我们使用邮箱和密码方式进行身份认证,因为这种方式是最简单的。

进入 Firebase dashboard ,点击 Auth,激活邮箱密码认证。

fb-auth-1

选中 SIGN-IN METHOD 标签栏,再在 Sign-in providers 那一节选中Email/Password 行,切换 Enable 并点击 SAVE:

authentication

Firebase 存储账户信息到 keychain,因此最后一步,在项目中,切换到 target’s Capabilities 打开 Keychain Sharing 开关。

keychain-sharing

现在,我们已经可以使用邮箱和密码进行身份认证了。

Registering Users

LoginViewController.swift,找到 signUpDidTouch(_:) 方法,这里会弹出 UIAlertController 让用户注册账号,定位到 saveAction 方法,添加以下代码到方法块儿。

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

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

以上代码解释:
1. 从弹框中获取邮箱和密码。
2. 调用 Firebase 方法 createUser(withEmail:password:),传递邮箱和密码给它。
3. 如果执行没有错误,用户账号即被创建。但是,我们还要再进行一下登录操作 signIn(withEmail:password:) ,同样需要传递邮箱和密码。

Build and run. 点击 Sign up ,键入邮箱和密码,点击保存。现在 view controller 还不能在登录成功后导航到其它地方。我们刷新 Firebase Login & Auth ,我们将看到新建的用户。

fb-register-user

喔!我们的 app 现在可以让用户注册并进行登录了,不过我们先不要庆祝,我们还需要再做些优化,好使用户更好的使用它。

Logging Users In

Sign up 按钮可以注册和登录,然而 Login 现在还什么都做不了,因为我们还没有给它绑定验证。

LoginViewController.swift, 找到 loginDidTouch(_:) 方法,修改如下:

@IBAction func loginDidTouch(_ sender: AnyObject) {
    FIRAuth.auth()!.signIn(withEmail: textFieldLoginEmail.text!,
                            password: textFieldLoginPassword.text!)
}

当用户点击 Login 时,这些代码将验证用户信息。
我们接下来需要在用户登录成功后导航到下一个页面。

Observing Authentication State

Firebase 有可以监控用户验证状态的观察者。这里是添加 segue 最好的地方。在 LoginViewController: 添加如下代码:

override func viewDidLoad() {
  super.viewDidLoad()      

  // 1
  FIRAuth.auth()!.addStateDidChangeListener() { auth, user in
    // 2
    if user != nil {
      // 3
      self.performSegue(withIdentifier: self.loginToList, sender: nil)
    }
  }
}

注释如下:
1. 使用 addStateDidChangeListener(_:) 创建验证观察者。该 block 被传入两个参数:auth 和 user。

  1. 测试 user 的值,如果验证通过,返回用户信息,如果验证失败,返回 nil 。

  2. 验证成功,进行页面跳转。传输 sender 为 nil 。这看起来有些奇怪,但是稍后我们将在 GroceryListTableViewController.swift 进行设置。

Setting the User in the Grocery List

GroceryListTableViewController.swift 文件 viewDidLoad(): 方法底部添加如下代码:

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

这里我们添加了一个 Firebase auth object 的验证观察者,当用户成功登录时,依次分配用户属性。

Build and run. 如果用户已经登录,app 将跳过 LoginViewController 直接导航到 GroceryListTableViewController. 当用户添加 items ,他们的 email 将显示到 cell 的详情里面。

fb-user-add

Success! app 现在已经有了基本的用户验证功能。

Monitoring Users’ Online Status

现在既然我们的 app 已经拥有了用户验证功能,那是时候添加监控哪个用户在线功能了。打开 GroceryListTableViewController.swift ,添加如下 property:

let usersRef = FIRDatabase.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 创建一个 child 引用,当 Firebase 创建一个账号时,这个引用会被生成。
2. 使用这个引用保存当前用户的 email.
3. 当 Firebase 连接关闭的时候,例如用户退出 app , 调用 currentUserRef 的 onDisconnectRemoveValue(),删除位置引用的值。这可以完美监控离线用户。

Build and run. 当 view 加载时,当前用户的电子邮件,会被添加在当前在线位置的一个子节点。

fb-monitoring

Great! 现在当用户数量增加时,是时候改变 bar button item 的个数了。

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 的 title 随之更新。

Displaying a List of Online Users

打开 OnlineUsersTableViewController.swift,在 class 的 property section 添加一个本地引用到 Firebase 的在线用户记录。

let usersRef = FIRDatabase.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. 创建一个 children added 监听器,添加到被 usersRef 管理的位置。这与值侦听器不同,因为只有添加的 child 被传递到闭包。

  1. 从 snapshot 获取值,并赋值给本地变量 array。
  2. 因为 table view 的坐标从 0 开始计算,当前的 row 总是等于 array 的个数 -1。
  3. 使用当前 row index 创建一个 NSIndexPath.

  4. 使用动画从顶部添加一行到 table view.

这将只渲染添加的条目,而不是重新加载整个列表,而且还可以指定一个漂亮的动画。:]

由于用户可以脱机,table 需要对被删除的用户做出反应。在我们刚刚添加的代码下面添加以下内容:

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 引用的子元素。它在本地数组中搜索电子邮件的值,以找到相应的子条目,一旦找到,它就从表中删除相关的行。

Build and run.

在 Firebase 用户仪表板上点击 Online ,当前用户的电子邮件将出现在表格中。使用一些技巧,可以在网上添加一个用户,一旦你做了,它就会显示在列表中。在仪表板上单击删除按钮,用户就会从 table 中消失….

fb-users-table

Booyah! 当用户被添加和删除的时候,table 随之更新了。

monintoring-users

Enabling Offline

杂货店因不稳定的数据连接而臭名昭著。你会认为他们现在都有了Wi-Fi,但是没有!

不过没关系,我们只需设置数据库离线工作。打开 * AppDelegate*,在(_:didFinishLaunchingWithOptions:) 底部方法返回 true 之前,添加如下代码:

FIRDatabase.database().persistenceEnabled = true

是的,就是这样! 就像我们的应用能够离线运行一样。当 app 重启,一旦建立网络连接,离线更新也将作用于我们的 Firebase 数据库。Oooh-ahhhh !

Where To Go From Here?

我们可以在这里下载 Grocr-final完整项目。

注意:下载完后,我们仍需要添加自己的 GoogleService-Info.plist 和 设置允许Keychain sharing

在这个Firebase教程中,我们通过构建一个协作的购物清单 app 了解了Firebase的基础知识,我们已经实现了将数据保存到一个 Firebase 数据库、实时同步数据、认证用户、监视在线用户状态以及实现了离线支持。所有这些都是在没有写一行服务器代码的情况下完成的! :]

如果你对 Firebase 感兴趣,请查看文档 documentation,以及 Firebase 提供的示例。

如果您对这个Firebase教程、Firebase或示例应用有任何意见或问题,请加入下面的论坛讨论!

                                                                     上海 虹桥V1 
                                                               2017.09.06 19:02
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值