Professional Documents
Culture Documents
com
Firebase Tutorial: Getting Started
In this Firebase tutorial, you’ll learn Firebase fundamentals including saving data, real-time sync, authentication, user status, and offline support.
4.6/5
19
Ratings ∙ Leave a Rating
Update note
Update note:: This tutorial has been updated for iOS 11, Swift 4.1, and Xcode 9.3 by Mikael Konutgan. The original tutorial was written by David
East.
Firebase is a mobile-backend-as-a-service that provides powerful features for building mobile apps. Firebase has three core services: a realtime database,
SDK, you can use these services to create apps without writing any server code.
user authentication and hosting. With the Firebase iOS SDK,
In this Firebase tutorial, you’ll learn the fundamentals of Firebase by making a collaborative grocery list app called Grocr
Grocr.. When items get added to the list,
they’ll appear instantly on any user’s devices, but you’re not going to stop there. You’ll tweak Grocr to work offline, so the list stays in sync even with a spotty
grocery store data connection.
As you work, you’ll learn about:
Saving data to a Firebase database.
Syncing data in realtime.
Authenticating users.
Monitoring online users.
Enabling offline support.
Get ready to realtime all the things!
Getting Started
Start by downloading the materials for this tutorial; you can find a link at the top or bottom of this page. This project uses CocoaPods to manage
dependencies and they are included in the downloaded projects.
This project contains three view controllers:
. LoginViewController.swift
LoginViewController.swift:: the login is currently using hard coded credentials, but you’ll fix that soon.
. GroceryListTableViewController.swift
GroceryListTableViewController.swift:: this is a subclass of UITableViewController that adds items to a list of local data using a
UIAlertController.
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 1/20
03/07/2019 Firebase Tutorial: Getting Started | raywenderlich.com
. OnlineUsersTableViewController.swift
OnlineUsersTableViewController.swift:: this controller will use Firebase’s presence feature to display all of the users currently online.
In addition to the view controllers, there are two models, GroceryItem.swift and User.swift
User.swift..
Build and run, and you’ll see the app looks like this:
Setting up a Firebase Account
There are three main steps to setting up Firebase in an iOS project:
. Create a free Firebase account
. Download and add GoogleService‑Info.plist to your app
. Tell Firebase to start when your app launches
homepage. Press GO TO CONSOLE in the top-right corner, and enter the credentials for your Google
To create a Firebase account, visit the Firebase homepage.
account, if you’re not signed in already. If you don’t have a Google account, you’ll need to create one first, which you can do here
here..
You’ll then have a clean Firebase console created for you. Don’t worry about forking over any money; everything in this Firebase tutorial can be done with
the free plan.
It’s time to create your first project, so click the + Add project button.
In the dialog that appears, enter Grocr as the Project name and select your preferred Country/region:
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 2/20
03/07/2019 Firebase Tutorial: Getting Started | raywenderlich.com
Click CREATE PROJECT, wait for it to create and then press Continue to be taken to your project’s dashboard:
This is a container for your project’s Firebase services. You’ll use it to store data and authenticate users.
Select the circle iOS button above Add Firebase to your iOS app. Enter rw.firebase.gettingstarted in the iOS Bundle ID field:
Click REGISTER APP and then click Download GoogleServiceInfo.plist. Follow the instructions and move it to the Grocr project in Xcode.
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 3/20
03/07/2019 Firebase Tutorial: Getting Started | raywenderlich.com
The starter project already includes the SDK, so just click CONTINUE
CONTINUE.. The last page explains how to connect Firebase when your app starts:
You need to do this in the tutorial app. In Xcode, open AppDelegate.swift and add this code before the return statement within
application(_:didFinishLaunchingWithOptions:)::
application(_:didFinishLaunchingWithOptions:)
FirebaseApp.configure()
FirebaseApp.configure()
Back on your Firebase project’s webpage, click FINISH to see your new project’s details:
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 4/20
03/07/2019 Firebase Tutorial: Getting Started | raywenderlich.com
That’s it!
Creating a Connection to Firebase
With your Firebase app set up, go to Xcode and open GroceryListTableViewController.swift
GroceryListTableViewController.swift.. Where the properties are defined, add the following:
let ref = Database.database().reference(withPath: "grocery-items"
Database.database().reference(withPath: )
"grocery-items")
// grocery-items/milk
"milk": {
"milk":
// grocery-items/milk/name
"name": "Milk"
"name": ,
"Milk",
// grocery-items/milk/addedByUser
"addedByUser": "David"
"addedByUser":
},
"pizza": {
"pizza":
"name": "Pizza"
"name": ,
"Pizza",
"addedByUser": "Alice"
"addedByUser":
},
}
}
In the JSON tree above, you can see there’s a path mapped to every piece of data. You can continue to traverse down the tree and retrieve data at deeper
locations.
In the case of the data above, you can retrieve all grocery items by using the path:
grocery-items
If you only want to get the first grocery item you can navigate its child path:
grocery-items/milk
Since all Firebase keys map to paths, the key names you choose are especially important.
Understanding Firebase References
A fundamental theme to grasp is that a Firebase reference points to a location in Firebase where data is stored. If you create multiple references, then they
all share the same connection.
Have a look at this sample code:
// 1
let rootRef = Database.database().reference()
Database.database().reference()
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 5/20
03/07/2019 Firebase Tutorial: Getting Started | raywenderlich.com
// 2
let childRef = Database.database().reference(withPath: "grocery-items"
Database.database().reference(withPath: )
"grocery-items")
// 3
let itemsRef = rootRef.child("grocery-items"
rootRef.child("grocery-items")
"grocery-items")
// 4
let milkRef = itemsRef.child("milk"
itemsRef.child("milk")
"milk")
// 5
print(rootRef.key)
print(rootRef.key) // prints: ""
print(childRef.key)
print(childRef.key) // prints: "grocery-items"
print(itemsRef.key)
print(itemsRef.key) // prints: "grocery-items"
print(milkRef.key)
print(milkRef.key) // prints: "milk"
Adding New Items to the List
Near the bottom of GroceryListTableViewController.swift addButtonDidTouch(_:)..
GroceryListTableViewController.swift,, find addButtonDidTouch(_:)
This is where you present the user with a UIAlertController to add a new item.
Inside the method, locate saveAction
saveAction.. Currently, it only saves the data to a local array, so saveAction won’t sync across multiple clients and disappears
when you restart the app.
Nobody’s going to want to use an app that doesn’t remember or sync their grocery list! Replace saveAction with the following:
let saveAction = UIAlertAction(title: "Save"
UIAlertAction(title: ,
"Save",
.default
style: .default) { _ in
default)
// 1
guard let textField = alert.textFields?.first,
let text = textField.text else { return }
// 2
let groceryItem = GroceryItem (name: text,
GroceryItem(name:
addedByUser: self .user.email,
self.user.email,
completed: false
false))
// 3
let groceryItemRef = self.ref.child(text.lowercased())
self.ref.child(text.lowercased())
// 4
groceryItemRef.setValue(groceryItem.toAnyObject())
}
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 6/20
03/07/2019 Firebase Tutorial: Getting Started | raywenderlich.com
Cloud Firestore is an alternative to the Realtime Database and is currently in beta. If you’re curious, you can learn more about it here.
In this Firebase tutorial, you’ll use the Realtime Database instead of Cloud Firestore. Select the dropdown next to Database and pick Realtime Database.
By default, the Realtime Database requires user authentication for reading and writing. When you selected test mode earlier, you set Firebase to always
allow both, to make it easier during development. Select RULES and verify the following in the editor:
{
"rules": {
".read": true,
".write": true
}
}
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 7/20
03/07/2019 Firebase Tutorial: Getting Started | raywenderlich.com
If they don’t match, replace them, then select the PUBLISH button to save your changes.
Build and run. In the Firebase dashboard, select the DATA tab and position the browser window next to the simulator. When you add an item in the
simulator, you’ll see it appear in the dashboard:
Now you have a grocery list app that adds data to Firebase in realtime! So this key feature is working correctly, but none of the items are added to the table
view.
So, how about you get that data synchronizing from the database to the table view?
Retrieving Data
You retrieve data in Firebase by attaching an asynchronous listener to a reference using observe(_:with:).
Add the following to the end of viewDidLoad() in GroceryListTableViewController.swift:
ref.observe(.value, with: { snapshot in
print(snapshot.value as Any)
})
Synchronizing Data to the Table View
Now it’s time to actually display the grocery list in your table view.
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 8/20
03/07/2019 Firebase Tutorial: Getting Started | raywenderlich.com
// 3
for child in snapshot.children {
// 4
if let snapshot = child as? DataSnapshot,
let groceryItem = GroceryItem(snapshot: snapshot) {
newItems.append(groceryItem)
}
}
// 5
self.items = newItems
self.tableView.reloadData()
})
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 9/20
03/07/2019 Firebase Tutorial: Getting Started | raywenderlich.com
Removing Items From the Table View
The table view will synchronize on any kind of change to your data, but right now there’s nothing to update Firebase when the user decides not to get that
pizza.
To notify the database of a deletion, you need to set a Firebase reference to delete an item when the user swipes it away.
Locate tableView(_:commit:forRowAt:). Right now, this method removes a grocery item from the local array using the index path’s row. It works, but
there’s a better way. Replace the existing implementation with the following:
if editingStyle == .delete {
let groceryItem = items[indexPath.row]
groceryItem.ref?.removeValue()
}
Firebase follows a unidirectional data flow model, so the listener in viewDidLoad() notifies the app of the latest value of the grocery list. A removal of an
item triggers a value change.
The index path’s row is used to retrieve the corresponding grocery item. Each GroceryItem has a Firebase reference property named ref, and calling
removeValue() on that reference causes the listener you defined in viewDidLoad() to fire. The listener has a closure attached that reloads the table view
using the latest data.
Build and run. Swipe an item, tap delete and watch it vanish from both your app and in Firebase.
Checking Off Items
Now you know how to add, remove, and sync items, and that’s all pretty cool. But what about when you’re actually shopping? Should you just delete stuff
that you’ve got, or would it be better to mark things off as you add them to your basket?
Back in the analog days of pens and paper, people used to cross stuff off the grocery list, so you’ll mimic that familiar behavior in this app, but with a modern
twist!
When tapped, items should turn gray and show a checkmark to give the user some visual feedback that the item is no longer needed.
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 10/20
03/07/2019 Firebase Tutorial: Getting Started | raywenderlich.com
Open GroceryListTableViewController.swift and find toggleCellCheckbox(_:isCompleted:). This method toggles the necessary view properties for
UITableViewCell, depending on whether its associated item is complete.
It’s called from tableView(_:cellForRowAtIndexPath:) when the table view is first loaded, and from tableView(_:didSelectRowAt:) when the
user taps on a row.
Replace the current implementation of tableView(_:didSelectRowAt:) with the following:
// 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
])
Congratulations, you’ve got yourself a pretty sweet grocery list app now!
Sorting the Grocery List
You know how sometimes you forget to pick up that ice cream because it’s nestled between a couple of things you’ve already marked off and your eyes played
tricks on you? Well you, dear reader, can fix that.
The app would be 10x more awesome if checked items moved themselves to the bottom of the list automatically. Then the remaining items would be clear
and easy for your eyes to see.
Using Firebase queries, you can sort the list by arbitrary properties. Still working in GroceryListTableViewController.swift, update the observer in
viewDidLoad() as follows:
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)
}
}
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 11/20
03/07/2019 Firebase Tutorial: Getting Started | raywenderlich.com
self.items = newItems
self.items
self.tableView.reloadData()
self.tableView.reloadData()
})
To order the data by the completed value you call queryOrdered(byChild:) on the Firebase reference, which takes a key to order by.
Since the list needs to order by completed, the key completed is passed to the query. Then, queryOrdered(byChild:) returns a reference that informs
the server to return data in an ordered fashion.
Build and run. Tap on a row to toggle its completion status. The completed items magically move to the bottom of the list.
Wow! You’re really making grocery shopping easier here. Seems like it should be simple enough to sync the data across multiple users, for instance, with a
significant other or housemate. This sounds like a job for…authentication!
Authenticating Users
Firebase has an authentication service that allows apps to authenticate through several providers. You can authenticate users with Google, Twitter,
Facebook, Github, email & password, anonymous, and even custom backends. Here you’ll use email and password because it’s the easiest to set up.
To enable email and password authentication go to the Firebase dashboard and click on Authentication
Authentication..
Select the SIGNIN METHOD tab and then, in the Signin providers section, select the Email/Password row. Click the Enable switch and click SAVE
SAVE::
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 12/20
03/07/2019 Firebase Tutorial: Getting Started | raywenderlich.com
Firebase stores credentials in the keychain, so as the last step enable Keychain Sharing in Xcode by navigating to your target’s Capabilities and toggling
Keychain Sharing
Keychain Sharing..
When prompted by Xcode, select your development team. This is required so Xcode can manage signing for you and enable the capability for the App ID
automatically.
Now you’re ready to authenticate users using their email and password!
Registering Users
In LoginViewController.swift
LoginViewController.swift,, find signUpDidTouch(_:)
signUpDidTouch(_:).. This presents a UIAlertController that allows the user to register for an account. Locate
saveAction and add the following to its closure:
// 1
let emailField = alert.textFields![0
alert.textFields![0]
let passwordField = alert.textFields![1
alert.textFields![1]
// 2
Auth.auth().createUser(withEmail: emailField.text!, password: passwordField.text!) { user, error in
Auth.auth().createUser(withEmail:
if error == nil {
// 3
Auth.auth().signIn(withEmail: self
Auth.auth().signIn(withEmail: .textFieldLoginEmail.text!,
self.textFieldLoginEmail.text!,
password: self .textFieldLoginPassword.text!)
self.textFieldLoginPassword.text!)
}
}
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 13/20
03/07/2019 Firebase Tutorial: Getting Started | raywenderlich.com
W00T! The app now registers users and then lets them log in. Don’t celebrate yet though, you need to finish the process so people can actually use the app as
intended.
Logging Users In
The Sign up button can register and log in users. However, the Login button effectively does nothing because no authentication is performed.
Still working in LoginViewController.swift
LoginViewController.swift,, find loginDidTouch(_:) and replace its implementation with the following:
guard
let email = textFieldLoginEmail.text,
let password = textFieldLoginPassword.text,
email.count > 0,
email.count
password.count > 0
password.count
else {
return
}
alert.addAction(UIAlertAction
alert.addAction(UIAlertAction(title: "OK"
UIAlertAction(title: "OK", .default
, style: .default))
default))
This code will authenticate the user when they attempt to log in by tapping the Login button.
You now need to perform the segue to the next controller only when the user has logged in.
Observing Authentication State
Firebase has observers that allow you to monitor a user’s authentication state. This is a great place to perform a segue.
Add the following to LoginViewController
LoginViewController::
override func viewDidLoad() {
viewDidLoad()
super.viewDidLoad()
super.viewDidLoad()
// 1
Auth.auth().addStateDidChangeListener() { auth, user in
Auth.auth().addStateDidChangeListener()
// 2
if user != nil {
// 3
self.performSegue(withIdentifier: self
self.performSegue(withIdentifier: .loginToList, sender: nil
self.loginToList, )
nil)
self.textFieldLoginEmail.text = nil
self.textFieldLoginEmail.text
self.textFieldLoginPassword.text = nil
self.textFieldLoginPassword.text
}
}
}
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 14/20
03/07/2019 Firebase Tutorial: Getting Started | raywenderlich.com
Setting the User in the Grocery List
Go to GroceryListTableViewController.swift viewDidLoad()::
GroceryListTableViewController.swift,, and add the following to the bottom of viewDidLoad()
Auth.auth().addStateDidChangeListener { auth, user in
Auth.auth().addStateDidChangeListener
guard let user = user else { return }
self.user = User
self.user User(authData:
(authData: user)
}
Here you attach an authentication observer to the Firebase auth object, which in turn assigns the user property when a user successfully signs in.
Build and run. If a user is logged in, they bypass LoginViewController and segue to the GroceryListTableViewController
GroceryListTableViewController.. When users add items,
their email will show in the detail of the cell.
Logging Users Out
Since users can login in, it makes sense they should be able to log out too. Open OnlineUsersTableViewController.swift and replace the code inside
signoutButtonPressed(_:) with this:
// 1
let user = Auth.auth().currentUser!
Auth.auth().currentUser!
let onlineRef = Database.database().reference(withPath: "online/\(user.uid)"
Database.database().reference(withPath: )
"online/\(user.uid)")
// 2
onlineRef.removeValue { (error, _) in
// 3
if let error = error {
print("Removing online failed: \(error)")
print( \(error)")
return
}
// 4
do {
try Auth.auth().signOut()
Auth.auth().signOut()
self.dismiss(animated: true
self.dismiss(animated: , completion: nil
true, )
nil)
} catch (let error) {
(let
print("Auth sign out failed: \(error)")
print( \(error)")
}
}
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 15/20
03/07/2019 Firebase Tutorial: Getting Started | raywenderlich.com
. You first get the currentUser and create onlineRef using its uid, which is a unique identifier representing the user.
. You call removeValue to delete the value for onlineRef. While Firebase automatically adds the user to online upon sign in, it does not
remove the user on sign out. Instead, it only removes users when they become disconnected. For this application, it doesn’t make sense to
show users as “online” after they log out, so you manually remove them here.
. Within the completion closure, you first check if there’s an error and simply print it if so.
. You here call Auth.auth().signOut() to remove the user’s credentials from the keychain. If there isn’t an error, you dismiss the view
controller. Otherwise, you print out the error.
Build and run, tap the left navigation item, press Sign Out
Sign Out,, and you’ll be returned to the login page.
Monitoring Users’ Online Status
Now that the app has user authentication, its time to detect which users are online. Open GroceryListTableViewController.swift and add the following
property:
let usersRef = Database.database().reference(withPath: "online"
Database.database().reference(withPath: )
"online")
This is a Firebase reference that points to an online location that stores a list of online users.
viewDidLoad()::
Next, add the following to the bottom of the addStateDidChangeListener(_:) closure inside viewDidLoad()
// 1
let currentUserRef = self.usersRef.child(
self.usersRef.child(self
.usersRef.child(self.user.uid)
self.user.uid)
// 2
currentUserRef.setValue(self
currentUserRef.setValue(self.user.email)
self.user.email)
// 3
currentUserRef.onDisconnectRemoveValue()
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 16/20
03/07/2019 Firebase Tutorial: Getting Started | raywenderlich.com
Great! Now it’s time to change the number of the bar button item as the user count grows.
Updating the Online User Count
Still working in GroceryListTableViewController.swift
GroceryListTableViewController.swift,, add the following code to viewDidLoad()
viewDidLoad()::
usersRef.observe(.value, with: { snapshot in
if snapshot.exists() {
self
self.userCountBarButtonItem?.title
.userCountBarButtonItem?.title = snapshot.childrenCount.description
} else {
self.userCountBarButtonItem?.title = "0"
self.userCountBarButtonItem?.title
}
})
This creates an observer that is used to monitor online users. When users go online and offline, the title of userCountBarButtonItem updates with the
current user count.
Displaying a List of Online Users
Open OnlineUsersTableViewController.swift and, just as you did before, add a local reference to Firebase’s online users record in the class’s property
section:
let usersRef = Database.database().reference(withPath: "online"
Database.database().reference(withPath: )
"online")
Then, in viewDidLoad()
viewDidLoad(),, replace:
currentUsers.append("hungry@person.food"
currentUsers.append("hungry@person.food")
"hungry@person.food")
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 17/20
03/07/2019 Firebase Tutorial: Getting Started | raywenderlich.com
This simply adds an observer that listens for children of the usersRef reference being removed. It searches the local array for the email value to find the
corresponding child item, and once located, it deletes the associated row from the table.
Build and run.
Tap Online in the Firebase users dashboard, and the current user’s email will appear in the table. Using a bit of trickery, it’s possible to add a user to Online,
and once you do, it shows in the list. Click the Remove button in the Dashboard and the user fades from existence.
Booyah! The table updates when users are added and removed.
Enabling Offline
Grocery stores are notorious for spotty data connections. You’d think they’d all have Wi-Fi now, but no!
No problem, you’ll just set up your database to work offline. Open AppDelegate.swift and add the following to the end of
application(_:didFinishLaunchingWithOptions:),, before return true:
application(_:didFinishLaunchingWithOptions:) true:
Database.database().isPersistenceEnabled = true
Database.database().isPersistenceEnabled
Yup, that’s it! Just like that your app works offline. Even offline updates that occur across app restarts will apply to your Firebase database once a connection
is made. Oooh-ahhhh!
Where To Go From Here?
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 18/20
03/07/2019 Firebase Tutorial: Getting Started | raywenderlich.com
You can get the completed version of Grocr from the downloadable materials below.
Note
Note:: You still have to add your own GoogleServiceInfo.plist after downloading the final project.
Throughout this Firebase tutorial, you’ve learned the basics of Firebase by building a collaborative grocery list app. You’ve implemented saving data to a
Firebase database, syncing data in realtime, authenticating users, monitoring online user status and enabling offline support. And you did all this without
writing a single line of server code! :]
To learn more about Firebase, please check out the documentation and the examples provided by Firebase themselves.
If you have any comments or questions about this Firebase tutorial, Firebase, or the sample app, please join the forum discussion below!
Add a rating for this content
raywenderlich.com Subscription
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 19/20
03/07/2019 Firebase Tutorial: Getting Started | raywenderlich.com
Full access to the largest collection of Swift and iOS development tutorials anywhere!
Learn more
https://www.raywenderlich.com/3-firebase-tutorial-getting-started 20/20