iOS Databases : Module 2, Enhancing the Learning App

Lesson 1 : Introduction

The second module of the CWC+ iOS Databases course begins with an introduction by Chris, going over familiar ground with setting up Firestore to work with our old Learning App project.

I’ve taken the opportunity here to copy my previous app, figuring out where to rename parts of the project to ensure it works, before beginning this module. Chris does provide a “working copy” of the app, but my version has all of my notes from the previous iOS Foundations course that I’d like to be able to refer to as we enhance the app.

The steps in this first lesson are effectively those that I’ve kept a note of over here : Setting up Cloud Firestore. As expected by now, Xcode takes its own sweet time “Building” for the first time, so I’ll have an early coffee break before the next lesson.

Lesson 2 : Loading the data into Firestore

Data transferred to Firestore

The second lesson involves moving our JSON data (both local to the app, and remote on GitHub), but there’s no easy way to do this and so Chris provides a “JSONtoFirebase” script.

This requires the obligatory waiting around for Xcode to “build” thousands of whatevers before we can procede. I can’t take another coffee so soon! Maybe I should go for a run whilst it gets itself sorted …

Lesson 3 : Retrieving the Modules

In the third lesson, Chris takes us through fetching the data from Firestore instead of locally.

A couple of highlights from this lesson includes Chris using as? (that odd thing that bugged me yesterday). He explained it that, as we don’t know what data type the database will return (because we’re fetching all key-value pairs) and we want it to be cast as a String, using as? allows us to do this without encountering errors.

I kind of get that. Swift is a bit like “we may get an error, so this is me handling it” whereas all of my coding in the past has been to ensure I didn’t get errors in the first place. Bit of a stretch for the ageing brainbox, but I’ll get there.

The other main point of note here is that we’re changing all of the models in Models.swift to have default (empty) values so that, when we create a new Module instance, we don’t have to declare initial values. This is useful to know for the future, because it’s much easier that assigning arbitrary default values further down the line in the code.

Lesson 4 : Retriving the Lessons & Questions

The final lessons from this module involves retrieving the sub-collections and populating our learning app modules. An interesting aspect from this lesson was that our previous NavigationLink to show a selected lesson would show a blank screen because the screen was being navigated to before the module data had time to be populated from Firestore.

To accomodate that delay, we change the destination of the NavigationLink to include a closure, thus:

The method has a completion handler (the data type is a method with no parameters and no return value):

func getLessons(module: Module, completion: @escaping () -> Void) {
    ...
}

We add a closure to the NavigationLink’s destination which loads only when the method is complete:

...
NavigationLink(
    destination:
        ContentView()
        .onAppear(perform: {
            model.getLessons(module: module) { 
                model.beginModule(module.id)
            }                                            
        }),
        ...
    }
...

An interesting point of note that isn’t mentioned in the video is that my list of lessons/questions comes up in a different order to the ones shown on Chris’ video. My guess is that the auto-generated ids assigned to the documents in Firestore, being different for whoever runs the previous JSONtoFirebase script, means they could be in a different alphabetical sequence to someone else.

In a production environment, I guess we’d use specific IDs rather than auto-generated ones, in order to avoid this potentially confused outcome.

Anyway, that ends Module 2. The next module deals with authentication on Firebase, so that each user’s data can be attributed to them rather than everyone using the same data.