Advanced Firestore


The course is part of this learning path

Start course
2h 13m

In this course, we're going to create a Snapchat clone using structs and various advanced techniques of Firestore.

Learning Objectives

  • Learn how to make a Snapchat clone
  • Understand all the features of Snapchat and how to set them up

Intended Audience

This course is intended for anyone who wants to learn how to develop apps on iOS.


To get the most out of this course, some basic knowledge of iOS development would be beneficial. We recommend that you take this course as part of the Developing Mobile Apps for iOS learning path.


Hi, within this lecture we're going to change our upload functionality so that we will have two images inside of only one document so that we can consolidate all snaps and show them in only one post. So, how are we going to do that? I'm going to show you a way to do that but you can actually come up with a better idea later on if you want. So, let me show you how this goes. When I upload an image, this will create a document because I'm making it do so, rather than uploading one single image, I'm going to upload an ImageUrlArray to the Firestore. And then later on I'm going to check to see if the snap owner has previously uploaded that snap. So, if that's the case, I'm just going to take the same document and upload a new version of that image array, so I'm not going to add a new document but I'm just going to update the current document, okay? So, before we go on and use the snap dictionary over here we're going to have a check. And, in fact, this is all related to storage over here, right? So, let me write Storage and from this point on we are working with Firestore. So, we're going to leave the storage as it is because we want to save them to the storage eventually anyway, but in the Firestore we're going to have an if statement. Before we do that, we have to have an if statement. So, as I said before, I'm going to check to see if this snap owner has a previously published snap on the Firestore. So, I'm going to go over here and say fireStore.collection Snaps, okay? And I'm going to have a whereField. So, this whereField will look for the snap owner. So, I'm going to say snapOwner, okay? And this will be EqualTo: UserSingleton.sharedUserInfo.username. And if that's the case, then I'm going to get the documents, I'm not going to add snapshot listener because I just need to do it once. So, I'm going to say getDocuments, and this will give me either a snapshot or an error. So, in here I'm going to check to see if error is not nil. So, if this is the case, I can just show an error message to the user, so let's say error.localizedDescription over here with double question marks with error, okay? And else, if that's the case, then I should have some snapshot, but in any case I'm going to check to see if snapshot. is empty is false, okay? And if snapshot is not nil. So, like this, snapshot is not nil, so if that's the case, then I should have the snapshot. So, I can come over here into a for document, a for loop, for document in snapshot!.documents, okay? So, I'm going to assign every document to a variable called document so that I can get to see its ImageUrlArray, okay? So, let me get the documentID because we're going to use it later on as I said before because we're going to update one single document, we're not going to create one. So, we need this documentID, right? So, you know how this works as well? We have seen this in the like functionality in the Instagram clone but don't worry, I'm going to show it anyway. So, after that we have to check to see the imageUrlArray. But right now we don't even have an imageUrlArray, we just have an ImageUrl. So, first, we have to make sure that we are saving this in an array, not a single string. So, I'm going to come over here to my initial saving function, and I'm going to call this imageUrlArray and I'm going to wrap this inside of an array braces so that it will be uploaded as an image array, imageUrlArray, okay? Actually, this is just a string, array string, okay? So, later on I can come over here to my if statement and I can check to see if I can get this imageUrlArray out of my Firestore. So, let me call this imageUrlArray and I'm using if var because I'm going to change it later on. So, rather than just saying if flat, you can just say if var, and just say document.get imageUrlArray, and I'm going to cast this as an array of strings like this, okay? If that's the case, if I can get it, what I want to do is to update this. So, I'm going to say imageUrlArray.append. I'm going to append the newly created imageUrl over here, okay? And I'm going to first cast this one more time. First, unwrap this one more time. And if that's the case, then I'm going to re-upload this to the Firestore so that I can update it in the document that I'm looking for. And the way to do this is to call Firestore one more time and go to the snaps and you have to specify the document path as well because we are only interested in that document. So, that's how you actually update a document. You can come over here and setData and remember we have to use this merge as well in order to prevent other values from the deleting as well. So, let's choose this one, and remember we have other values over here and if we don't say merge, it will delete the existing one and we will only end up with the imageUrlArray and we will lose the post owner and date values. So, merge will be true, okay? And the error will be given to us if there is any error. You can check to see if error is not nil or is nil, actually. So, if error is nil, then we want to go to our FeedVC over here, but right now let me create my additionalDictionary because we are just doing an additional information over here, we're just uploading an incremental information. So, we're going to upload the imageUrlArray only and it has to be exactly the same. So, it has to be spelled exactly the same, okay? So, be aware of that and you can come over here and say additionalDictionary. So, that's it, that's how you update the value, okay? And, of course, you're going to have to cut this from here because if that's the case we don't want to do that, right? But if that's not the case, then after uploading my image to the storage, then after I check to see if this snap owner has a previous snap and if that's the case I'm doing my thing to update the value, okay? And if that's not the case, if this user doesn't have a previous snap in the Firestore, then I should just create a new document, right? So, I can come over here to if var or I believe, yep this, we have to come over here. Actually, we have to come over to the snapshot, right? If snapshot is not nil it means that I have a snapshot and I have a previous snap over here. So, if I say else, then I can just cut my uploading function to here so that if the user doesn't have any previous snapshot, if the user doesn't have any previous snaps then I can just upload a new one so that I can create a new document over here, right? So, this is how our upload functionality will look like. This is a little bit complicated than what we have been doing so far but this will give us a great structure to continue building our Snapchat clone. So, if we succeed over here it will take us to the Tab Bar Controller and if we succeed over here it should take us to the Tab Bar Controller Index one as well, Index zero as well. So, I'm going to say self.tabBarController?.selectedIndex is zero and of course I'm going to change the upload image view as well and I'm going to call this UIImage and it will have the name of selectimage.png. Let's see, select image.png, yes. So, here we go. Now, we are ready to test this. So, let me come over to my Firestore and delete everything before we test this because I want to see if my original functionality stays the same or not and we don't have imageUrlArray inside of that document anyway. So, after deleting everything, just run your new code in the simulator and there comes the moment of truth. So, let me come over here and upload new things, okay? Like this one, this monkey, and hit the 'Upload' function, and here we go. Now, we are inside of the feeds. So, if I come over here and refresh this, I can see the newly created document, right? So, let's select that document and here you go. Now, we have an imageUrlArray rather than an imageUrl string. So, let's try to add one more image to see if we get the additional image over here. So, if I click on over here and select another picture like this, okay? And upload it. So, pay attention to the Firestore, let's see what will happen. Here you go. Now, it got uploaded and it didn't change the document at all but it only added one imageUrl to the imageUrlArray and that's exactly what I want. As you can see, now we are seeing the real time updates. So, let me try this one more time and so that we can see it one more time, okay? Pay attention to the Firestore once I hit the 'Upload' button. So, here we go, we click the 'Upload' button it takes a little bit time, but it adds the imageUrl to the imageUrlArray. Now, we can use that to create our post, to create our snaps, and everything. So, that's it for the upload functionality, now it's time to retrieve those data to show them in Feed View Controller. Let's do that in the next lecture.


About the Author
Learning Paths

Atil is an instructor at Bogazici University, where he graduated back in 2010. He is also co-founder of Academy Club, which provides training, and Pera Games, which operates in the mobile gaming industry.

Covered Topics