Wisdom Ekpot A student of Ibom Metropolitan Polytechnic studying computer engineering, Wisdom has been writing JavaScript for two years, focusing on Vue.js, Angular, and Express.js.

Firestore in Swift tutorial

5 min read 1457

Firestore In Swift Tutorial

Swift is a general-purpose, multiparadigm, compiled programming language developed by Apple, used specifically for iOS development. When writing any Swift application, developers usually want to add a database feature to their applications. This is where Firestore comes in.

Firestore is a NoSQL document database built for automatic scaling, high performance, and easy application development. In Firestore, all data has a set of key-value pairs and is stored in a collection.

In this tutorial, we will learn how to set up and configure Firestore in our Swift application. Firestore makes it easy to store data in the cloud while managing authentication and security without requiring a backend developer.

Firestone in Swift prerequisites

To begin this tutorial, ensure you have the following:

  • Familiarity with Swift programing
  • Familiarity with SwiftUI
  • Xcode installed on your local machine
  • Online Swift Playground for Windows users
  • CocoaPods installed

Setting up the Swift project

Let’s start by creating a new Swift application. Open the Xcode application and select App to scaffold a new project.

Create A New Swift App By Clicking The App Button

Name the application, click the Next button, and choose where to save your application on your local machine.

Save Swift App To Local Machine

After setting up the project, we must initialize our pods and update the
Podfile through our terminal. To do this, first move into the project directory and run this command:

pod init;open Podfile 

pod init initializes the pods while open Podfile opens a config terminal to update the Podfile.

We made a custom demo for .
No really. Click here to check it out.

We must also include the Firebase pods for Podfile by including the following:

pod ‘Firebase/Core'
pod ‘Firebase/Firestore' 

You can see this configuration executed in the terminal.

Adding Firebase Pods In The Terminal

After doing this, press Command + S to save the Podfile and close the terminal editor.

Bringing in Firestore dependencies with CocoaPods

Next, let’s install our pods by running pod install to bring in the Firestore dependencies.

If you get the error below while trying to install the pod, install cocoapods on your local machine by running sudo gem install cocoapods. CocoaPods is a dependency manager for Swift that manages installing dependencies in our Swift application.

CocoaPods Error Highlighted In Terminal Indicating Need For CocoaPods Update

After installation, use the pod setup command to update cocoapods.

If the error persists, use brew to install cocoapods with the following command:

brew install cocoapods

Then, use this command to overwrite the older version:

brew link --overwrite cocoapods

With this done, you can now run pod install to install the dependencies for our application.
After installing the pods, open the project directory and open the funfirebase.xcworkspace file in Xcode.

Setting up Firebase

Now, head over to https://console.firebase.google.com/ and click the Create a project button. Enter a project name, such as “funfirebase.”

Creating A New Firebase Project Named funfirebase

Click the Continue button, disable Google Analytics for this project, and click the Create project button.

Once finished setting up the project, click the iOS icon to launch the setup prompt.

Launching The iOS Setup Prompt In Firebase By Clicking iOS Button

Add the application bundle identifier and click the Register app button. The application nickname and App Store ID is optional, so we can ignore that.

Adding The iOS Bundle ID To Firebase

Next, click the Download GoogleService-Info.plist button to download the iOS config. After downloading this file, move the file into your root Xcode project.

Download The iOS Config For Firebase By Clicking The Download GoogleService-Info.plist Button

Setting up the Firestore SDK

The Firestore SDK manages the full set of data in your Cloud Firestore project. To begin setting this up, open the funfirebaseApp.swift file, create a funfirebaseApp extension, and add an initFirebase method.

Extensions in Swift add new functionalities to an existing class, structure, enumeration, or protocol type:

extension funfirebaseApp {
  private func initFirebase() {
    FirebaseApp.configure()
  }
}

The FirebaseApp.config method configures a default Firebase app for our application. We have to initialize the initFirebase method by invoking it in our funfirebaseApp struct:

@main
struct funfirebaseApp: App {
    // init firebase
    init() {
        initFirebase()
      }

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

Building a Swift to-do application with Firestore

We are going to build a simple to-do application, which will add a list of tasks for users. The purpose of building this project is to help us understand how to add and retrieve data from the Cloud Firestore.

Let’s start by creating a simple UI for our application and use SwiftUI for our implementation. First, open the ContentView.swift file and update it to the following:

//
//  ContentView.swift
//  funfirebase
//
//  Created by Wisdom Ekpot on 7/19/21.
//

import SwiftUI

struct ContentView: View {
    @State private var task:String = ""
    var body: some View {

        // input field
        TextField("Start typing a task...", text: $task)
            .padding()
            .border(Color.black)
            .frame(minWidth: 100, idealWidth: 150, maxWidth: 240, minHeight: 30, idealHeight: 40, maxHeight: 50, alignment: .leading)

        // button to add
        Button(action: { print("Task added \(task)")}) {
            Text("Add Task")
        }.padding()
        .foregroundColor(.white)
        .background(Color.black)
        .cornerRadius(5)


        //
        NavigationView {
            List {
                Text("Read")
                Text("Execise")
                Text("Text John")
                Text("Say hello")
            }.navigationTitle("All Tasks")
        }

    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ContentView()
        }
    }
}

Let’s break down the code. We start by creating our input field:

 TextField("Start typing a task...", text: $task)
.padding()
.border(Color.black)
.frame(minWidth: 100, idealWidth: 150, maxWidth: 240, minHeight: 30, idealHeight: 40, maxHeight: 50, alignment: .leading)

Using the TextField property, we create input fields in Swift, including a defined minWidth and minHeight and a default placeholder. The task variable, defined in the body variable, stores the input field state:

@State private var task:String = ""

The next thing we’ll add is a button to add a to-do task to our Firestore database:

// button to add
        Button(action: { print("Task added \(task)")}) {
            Text("Add Task")
        }.padding()
        .foregroundColor(.white)
        .background(Color.black)
        .cornerRadius(5)

This assigns an action to the button to print the value of the input field.

Next, use the List property to list all the to-do items:

 // list all items
        NavigationView {
            List {
                Text("Read")
                Text("Execise")
                Text("Text John")
                Text("Say hello")
            }.navigationTitle("All Tasks")
        }

With the list defined, we can now preview our application on any simulator device. This tutorial uses iPhone 11 to preview the application, and it should look like this:

Preview To-Do List App With To-Do Tasks Listed

Adding the app’s functionalities

We will continue by creating the get and add functionalities. With these two functionalities added, users can add a new to-do task and get the list of all to-do tasks in the application.

Let’s start by creating a model for our to-do list. Create a Models directory. Inside, create a Todo.swift file and add the following code snippet:

import SwiftUI
struct Todo: Codable, Identifiable {
    var id: String = UUID().uuidString
    var name: String?
}

Our to-do list follows this data structure.

Next, create a viewModel directory, inside the directory, create a TodoViewModel.swift file and add the following code:

import Foundation
import FirebaseFirestore

class TodoViewModel: ObservableObject {

    @Published var todos = [Todo]()

    private var db = Firestore.firestore()

    func getAllData() {
        db.collection("todos").addSnapshotListener { (querySnapshot, error) in
            guard let documents = querySnapshot?.documents else {
                print("No documents")
                return
            }

            self.todos = documents.map { (queryDocumentSnapshot) -> Todo in
                let data = queryDocumentSnapshot.data()
                let name = data["name"] as? String ?? ""
                return Todo(name: name)
            }
        }
    }

    func addNewData(name: String) {
           do {
               _ = try db.collection("todos").addDocument(data: ["name": name])
           }
           catch {
               print(error.localizedDescription)
           }
       }
}

We have two functions here: the getAllData function gets all the data from our Firestore database, and the addNewData function adds a new item to the Firestore database.

To use the TodoViewModel.swift file, we must connect it to our ContentView.swift file inside our ContentView struct:

@ObservedObject private var viewModel = TodoViewModel()

With this defined, we must update our List element to the following:

 List(viewModel.todos) { todo in
                            VStack(alignment: .leading) {
                                Text(todo.name ?? "")
                            }
                        }.onAppear() {
                            self.viewModel.getAllData()
                        }.navigationTitle("All Tasks")

Of course, this renders a blank list because we don’t have any to-do tasks in our database.

To add the to-do tasks, head over to the Firebase console and click Firestore Database. Click the Create database button and select the Start in test mode radio button.

Create Firestore Database Page

With this done, we can start adding to-do tasks into our database.

Adding To-Do Tasks Firestore Directory

Click the Start collection link and add “todos” as the collection ID.

Adding Todos Collection ID

Now, start adding new to-do items into the database. Always set the field name to name.

Add To-Do Tasks In Database

Clicking the Save button automatically updates the application with our changes.

To-do Task Application With One Task And Button To Add More Tasks

Implementing the add functionality

We must also update our button to call the addNewData function that we created. We must add a task name as a parameter, which is retrieved from the input field.

To do this, modify the button to the following:

 Button(action: { self.viewModel.addNewData(name: task)}) {
            Text("Add Task")
        }.padding()
        .foregroundColor(.white)
        .background(Color.black)
        .cornerRadius(5)

Now, when clicking the button, it gets the value from the input field and passes it in the addNewData parameter, storing it in the Firestore collection.

Conclusion

Using Firestore in our Swift application is quite easy and straightforward. In this article, we have learned how to use SwiftUI to set up a user interface for our application and how to add and retrieve data from the Cloud Firestore.

Click here to get the source code of this application.

: Full visibility into your web apps

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.

.
Wisdom Ekpot A student of Ibom Metropolitan Polytechnic studying computer engineering, Wisdom has been writing JavaScript for two years, focusing on Vue.js, Angular, and Express.js.

Testing accessibility with Storybook

One big challenge when building a component library is prioritizing accessibility. Accessibility is usually seen as one of those “nice-to-have” features, and unfortunately, we’re...
Laura Carballo
4 min read

Leave a Reply