Hey, guys. In this lesson, we're going to be learning how to use Cloud Firestore. Firebase's main product, 1
essentially, and we're going to be using it to store the messages that our users sent. 2
So, first of all, head over to the documentation page Firebase on google.com/docs/guides. 3
And here you're going to navigate to Cloud Firestore and we're gonna go to the Get started section. 4
So feel free to have a read around if you have a moment. 5
But, essentially, we're going to follow this guide step by step like what we did with the authentication 6
module. 7
So the first thing we have to do is to create a new database. 8
Let's head over to our console and select our Firebase app. 9
So mine was called Flash Chat iOS13. And now we land on our console page for this project. 10
So we're going to select the database tab over here on the left. 11
And notice how Firebase actually has two different databases. 12
One is the brand spanking new Cloud Firestore which has now been officially released, and the other 13
is the real time database which was their original product. 14
Now, there's actually a section on "Find out if Cloud Firestore is right for you." 15
So choosing between these two databases. But, basically, the overview of it is that realtime database 16
was their initial product. And it was just a way of being able to save JSONS in the Cloud. 17
But as more and more people started using Firebase, they wanted more features, and especially things like 18
querying and ordering, and the kind of things that you get from modern databases like MongoDB. 19
So Cloud Firestore is the solution, 20
and that is what we're going to be learning how to use in this module. 21
Now, in terms of the dynamics at Firebase, even though they are still supporting realtime database, 22
you can see that they're really trying to hide it by putting it all the way down here. 23
And I have a sneaking suspicion that because it's Google, you never know what they do with the older 24
products. And if there isn't enough demand, then I don't know how long they'll still maintain that 25
realtime database. 26
So let's learn the latest and greatest. 27
Go ahead and click on this button, create database under Cloud Filestore. 28
Now, we get to set the rules for how to access our Cloud Firestore. 29
We can either start in production mode which will not allow any third party, so any of the apps or any 30
users to read and write, which is going to make it very hard to test our app, or we can start in test 31
mode which allows anyone with a reference to our database to be able to read or write to it for 30 days. 32
And this is perfect 33
while we're getting up and running and testing our app. And we're going to be using the test mode until 34
we're ready to add some rules around who's allowed to read and write from our database which we'll do 35
at the very end. 36
So let's go ahead and select test mode, and then hit next. 37
And now we get to choose a Cloud Firestore location. Now, the location that you choose 38
doesn't really matter that much, unless you have a lot of users, because, obviously, the closer you are 39
in terms of your region to your end user, then the faster will be to retrieve things from the database. 40
But note that there's also differences in cost. 41
So, for example, certain areas will cost more than other areas. 42
I recommend going with just us-central, 43
and this is the default selection, and then go ahead and click Done. At this point, with our small amounts 44
of data, 45
you really won't notice a difference in speed. 46
Now, it's going to take a little while to create your Firestore. 47
But once this loading screen is done, it will take you to your brand-new database. 48
So now we're ready to start creating some documents in our database. Heading back to the docs, 49
we've already completed this step creating the Firestore database on Firebase. 50
And we've also already set up our development environment. 51
So when we install the Firebase Authentication Module, we also added the Firebase Firestore pod. 52
So if we take a look in our project and you take a look down here where you've got pods and pod file, 53
you can see we've already got Firebase/Auth and Firebase Firestore. 54
Now, notice how here, they've also added Firebase Core which is the core module that these Firestore modules 55
and authentication modules all depend on. 56
But since a few months ago, it no longer is required for you to explicitly add the pod into your pod 57
file. 58
So we're actually good to go. 59
And this optional part if we're using Swift extensions, we actually don't need either. 60
So the only thing you need is this Firebase firestore. And in order to check to make sure that that's 61
already been added, 62
if you go down here and you expand the Pods folder, you should be at to see a module called Firebase 63
Firestore. 64
If you see that, then you're good to go. 65
So the next step is to initialize our Cloud of Firestore. 66
So in our AppDelegate.swift, 67
we've already imported Firebase and we've already configured the Firebase app in order to use Firebase 68
Authentication. 69
But now we're also going to use the Firestore module to create a new database. 70
So let's copy this line of code and let's go into our AppDelegate.swift, and just below where we've 71
configured our Firebase app, 72
I'm going to paste that line right here. So this line of code creates our Firebase Firestore. And to 73
test to make sure that it actually is working and creating that Firestore, 74
we're simply going to go ahead and print the db. 75
So let's go ahead and run our app so that the AppDelegate gets triggered and when our app has finished 76
launching. 77
So when we see our welcome screen, then that means this block of code has been triggered. And, indeed, down 78
here, 79
I see my Firestore reference being printed. 80
So that means that this line of code is working and we're now ready to move on to the next step. 81
Now, if you don't see this, the first thing I recommend you check is that your pod --version 82
is 1.8.4 or above. 83
I've noticed that if I haven't updated my CocoaPods and I'm using a lower version, when I tried to install 84
Firebase Firestore, this line of code doesn't actually work and I don't get anything printed, or I end 85
up with a crash. 86
So check that your version is higher than this 87
and if it's not, then be sure to run sudo gem install CocoaPods, so that you install the latest version 88
of CocoaPods and it gets updated. But if like me, you're getting that reference printed, then it means 89
that we're ready to go ahead and put in some data. Heading over to the ChatViewController, we're going 90
gonna go ahead and create our first piece of data based on what the user has typed in. And the time point 91
where we actually send our data to our Firestore should be the moment that the user presses the send 92
button, 93
so inside this IBAction. The first thing that I'm going to do is I'm going to create a Constant that 94
stores the message body. 95
So this is going to be equal to whatever is inside our messageTextField at the moment when the user 96
presses the send button. Because if you think about it, once they've typed a message and they're done, 97
then they're going to press on this little button and it's in that moment in time where we grab hold 98
of the text inside this text field, and we set it as the message body ready to be sent to our Firestore. 99
So I'm gonna set the message body to messageTextField.text. 100
And next, I want to also create the sender part of my message. Because remember, if you take a look inside 101
our message model, we've got two properties: a sender and a body, which we need to fill. 102
So we've already got the body. But how do we get hold of the sender? 103
How can we get hold of the logged in users' 104
email address? 105
Well, if we take a look back at the documentation for Authentication and under iOS, if we take a look 106
at the Manage Users section, you can see that you get hold of the currently signed-in user by tapping 107
into the current user property. 108
And this happens to be a optional because if there's no user signed in, then current user is going to 109
be equal to nil. 110
And in Swift, things are only allowed to be equal to nil when they're an optional. 111
So heading back to our project, we're going to create a constant code messageSender and we gonna set 112
it to equal Auth.auth().currentUser. So Auth.auth().currentUser 113
and this is a user question mark. 114
So we don't just want the user though, 115
we can't do anything with that. 116
What we actually want is to drill even one level deeper and we're going to write .email. 117
So if we have a current user, then we're going to get a hold of their email and save it inside 118
our messageSender property. 119
Now notice how this is a optional string. 120
And this is also an optional string because the text field could be empty, 121
that might not be any text. 122
So it makes perfect sense to use an "if let" to actually bind both of these options to a constant as 123
long as they are not nil. 124
Now, we've said if the messageTextfield.text is not nil, then save it inside message body. If there 125
is a current user logged in, then save their email inside the messageSender. 126
And now if these two pieces of information are not nil, then we go into this block of code where we can 127
send these pieces of data to our Firebase Firestore. The first thing that I'm going to do here is I'm going 128
to create a reference to our database at the very top. 129
So I'm going to call this again db and I'm gonna set it to equal Firestore.firestore. 130
Now, once I've created that reference, then I can use it down here. 131
So how do we use it? 132
Well, if we take a look at the getting started section for our Cloud Firestore, you can see that you 133
can add pieces of data by tapping into a collection, and then using the addDocument method to send a 134
dictionary over. 135
So let's try this out. Let's tap into our database, and then tap into a collection. 136
Now, this collection expects a name as a string. 137
Now, in our case, we're probably going to call it messages. But just to make sure that we don't make any 138
typos in the future when we access this collection. 139
So when we're trying to retrieve from it, we're going to use our constants. 140
So we're going to use our collectionName here. 141
And notice how in this case, this constant collection name is inside a struct called FStore. But the 142
FStore struct is itself nested inside the K constant struct. 143
So in order to access this piece of information, we have to drill two levels deep. 144
So we'll write K.FStore.collectionName. And while you could put all of these constants simply 145
at the top level inside the K struct, it makes it easier this way that you can organize them into different 146
groups. 147
And when you call them in the code, it makes a little bit more sense. Say, the collectionName is associated 148
with the Firebase Firestore from the constants file. At least, I think this is more readable and slightly 149
better code. So now that we've tapped in to this collection which is code messages, let's go ahead and 150
call that method addDocument, and we're going to call the one which has a completion handler, so that 151
we'll hear if there are any errors. 152
Let's go ahead and hit enter to insert this bit of code. And the data that I want to send is, of course, 153
is going to be a dictionary. 154
And so it's going to have a key value pair. 155
And notice if I just back up a little bit that the key has to be of type String, 156
nut the values can be Any data type, 157
so it can be an object from a structure or a class. 158
And, essentially, it doesn't matter what it is. 159
Firebase doesn't actually care. 160
So let's go ahead and add our data. And the first piece of data is going to have a key using 161
the K.Ftstore.senderField, and then after a colon, we're going to add the value. 162
So in this case, the value is going to be that messageSender here. 163
So we'll call it messageSender, and then we're going to add a comma to add the next key which is going 164
to be K.FStore.bodyField, and this is going to be equal to the messageBody that we created 165
up here from what the user typed in the messageTextField. 166
Now that we've created our data dictionary, we're ready to create the completion handler. 167
So selecting this placeholder, go ahead and hit enter, and give the error a name of error. 168
And inside this completion block, we're going to check to see if let e = error. 169
So remember, this isn't optional, we might get no error at all. When this case, we're going to print out 170
the error. 171
I'm going to say, "There was an issue saving data to Firestore," and then we're going to just add that 172
"e" right at the end, so that it gets printed out 173
if it's not nil. But we're going to have an "else" statement as well. 174
So if there were no errors when this case, let's print "Successfully saved data." Let's go ahead and hit 175
save and run our app and test it out. 176
So I'm going to log in as 1@2.com. And here, I'm going to type a message. 177
Now, notice that if you have the keyboard enabled, it completely obscures that text field and the send 178
button. 179
We're going to sort this out in a little moment and we're going to make this text field go up to the 180
top and animate alongside the keyboard. 181
But for now, what I want you to do is to either go to Hardware Keyboard and Toggle Software Keyboard, 182
so you can make it go down essentially, or you can use the shortcut command K to do the same thing. 183
Basically, we want to be able to see what we're typing here. 184
So I'm going to write a test message and I'm going to click the send button to trigger our code here. 185
And notice how we've already got that callback completed and we've got successfully saved data printed, 186
so that means there were no errors, 187
and, hopefully, if we go into our Flash Chat iOS 13 database, and we hit refresh on this page, we should 188
be able to see our data being added in here under a collection code messages. And, indeed, there it is. 189
So we've got the body, which is text message, and we've got a sender, which is 1@2.com, and then 190
we've got this I.D. for this piece of data which is automatically created whenever we add a new document 191
to the Firebase Firestore. That's it. 192
There it is. 193
We've managed to save our very first piece of data to our Cloud-based database using Firebase Firestore. 194
In the next lesson, 195
I'm going to show you how we can retrieve data and read from our Firebase Firestore in order to populate 196
the cells of our Flash Chat app. 197
So for all of that and more, I'll see you there.