In this course, we're going to create an Instagram Clone and learn how to work with cloud servers using Firebase. By the end of this course, you will be well-equipped to build your own apps!
This course is designed for anyone who wants to:
- Learn about iOS development and coding
- Move into a career as an iOS developer
- Master Swift skills
To get the most out of this course, you should have some basic knowledge of iOS.
Hi, within this lecture, we're going to see how we can retrieve information from the Firestore database. So, far we have created view FeedViewController. All we have to do is get the information from database and assign to those views. So, in here we have our documents, right? All we have to do is just find a way to get those documents. So, if we go to the Documentation and if we click on the iOS, we can see how to get those values from the Firestore database as usual. So, in the left hand side we see the Cloud Firestore. And in here we have the read data. So, let me click on this get data once. And as you can see we have two options. We can use this get data once in order to get this data for one time only, okay? And this is get document. And we can have another option as well. We can listen for changing values. So, we can listen for real-time updates. So, if you click over here, you will see that rather than saying get document we say, add snapshot listener in here. So, it listens for changes, and if it sees any change in the database, so it makes us aware of the new values so that we can update our views in real time. So, let me show you how it's done. We have to create a new function in here. And in fact we don't have to create this function but it would be much better because it's going to be some kind of long function and I don't want to feel uphold viewDidLoad with this. So, I'm going to create this get data from Firestore and write related code in here. So, I'm going to create my fire store database. So, it's going to get from firestore.firestore, but of course in order to do that, I have to import Firebase in this FeedViewController as well, right? So, this is the same thing as we did before, so firestore.firestore. So now, I can use this database to add a snapshot listener in here. And in order to do that, you can say firestoreDatabase. and you have to specify the collection, okay? Remember what our collection was, we are using posts, and after that you can add the snapshot listener. but before we move on to that, I just want to show you a setting related to fieldvalue.server timestamp. So, previously, we had to do this; we had to create a settings for Firestore database, okay? And then in the settings, we have to say settings.setTimestampsInSnapshotenabled So, as you can see this is now deprecated, meaning that we don't currently use this, but in any case I just wanted to show you if you get any error regarding to fieldvalue.timestamp, maybe you may want to implement this so that you don't get any crash or error later on, but for right now as you can see we are not no longer using this because it's currently coming through as default, okay? So, this is true by default and we don't have to implement this, but if we have to, we can just say firestore database dot settings is settings, okay? But I'm not going to do that anymore so I'm going to comment this out like this, okay? /* */, so it won't get run, but I just wanted to show you just in case. And after that, we have to say FireStoreDatabase.collection. We're going to get our data from a specific collection. And as you know, our collection is posts. So, if you say .collection, let's go back to our database, we're going to say posts and then you can just say add snapshot listener, okay? So, this is what we want. This is how we get the query snapshot block. And you're going to see what the query snapshot is. If you hit "Enter", you will see that we get either a snapshot or an error. So, you can write snapshot or error in here. And we're going to start by checking to see if error is not nil. Of course, if it's not nil, I'm going to print the error or you can just create an alert message as well, okay? And else if this is not nil, if this is actually nil, it means that we get a snapshot. So, what is a snapshot? If you write snapshot you will see that this is a query snapshot type object, okay? And in this snapshot, we can find our documents. That's what we're trying to find, right? So, how do we get that document? If you say snapshot.documents, it gives you an array in which you will find query documents snapshots. So, this is actually a collection of documents together. So, this contains all of the documents inside of our post collection. So, if we do a for loop in here, we can iterate through all these documents one by one. And that's exactly what we are looking for. If we were to find another documentary, if we were to find another snapshot, we could have just come over here and say something like .document. And if I give a manual string in here like a document ID, it will just go into that document and I can come over here to say .collection and I can give another value as well. So, whatever level you want to go you have to specify in your code. Right now, I'm only interested in the documents under posts. So, I'm leaving it as it is, but if you want to get a specific document for example, you can get the document ID and write .collection posts, .document document ID and it will only bring the value of that current document. So, now if I say snapshot.documents I will get my array, but before I do that I'm going to check to see if snapshot.isEmpty is not true, okay? Or is not true or is false. So, I'm going to do this only and only if my snapshot is not empty. And since we're going to work with the snapshot dot documents, maybe you may want to add something like snapshot is not nil as well and I know this is not going to be nil because we're checking for errors and since snapshot is not empty, it means that snapshot is not nil. I know but just to be on the safe side, I'm being extra cautious in here because later on I'm going to loop through` all these documents. I'm going to say snapshot.documents I'm not making this optional. I'm just first unwrapping this. I can easily do that because I have checked for everything up until this moment, right? So, this is not going to be nil, not going to be empty. And I'm going to say for document in snapshot! .documents. So, it will give me every document in here. So, this is query document snapshot referring my individual documents right now. So, I can get any value from a document I want by saying document.get. So, as you can see document is now a string to any dictionary. So, this is a real dictionary and I can say .get and it will give me an optional any object, okay? And if I say document ID for example, I can just get the document ID as well. So, I can cast this to a variable and I can use it later on if I want. So, let me print this for right now. And we can see if we are getting the result that we want. So, let me call this from my viewDidLoad, okay? And I'll run it on my simulator. So, if you're working with a different structure of Firebase or Firestore, all you have to do is just make sure you're getting the right document IDs, and you can use this technique to check your document IDs as you can see we have these values and they are the same with these documents. So, I am sure that I'm getting the right document in here, okay? Now, I can process this dictionaries. I can process these dictionaries and get those values. And I know my field values right, field names actually. I know if I say documents.get, I have to say something like postedBy or postComment For example, let's say postedBy, it will give me the value of this and it has to be exactly the same postedBy with upper case B in our case. And this will be an optional any object. Remember it gives us an optional array because we have casted this as any before when we upload these values. So, all we have to do is just optionally cast this to a string and I'm going to use if let to do that. I'm going to say if let postedBy = document.get('posteBy') as string, okay? So, if we can do this, it means that we're getting our postedBy. So, let me print this right now, and let me delete this document ID. So, we can just see the postedBy values. And we're going to see James@metallica.com, because I believe we have done both posts with James@metallica.com. And here you go. We see the usernames right now. So, that's cool. So, we may proceed with other values as well. Now in here, if you want, you can do a nested if statement like we did in the Art Book, okay? And you can just write everything in here as well, or you can just create this if let 1x1 within the for loop. And it depends on your needs. So, if you want to do everything at once and if you don't want to proceed, if you don't get the name, you may want to do this with a nested loop, nested if control. So, let me create our arrays first because we need some arrays to store those information and then connect them to our views inside our cell for TableView function, right? So, we're going to have a user email, user command. And remember, our like array will be an integer array; it's not string, okay? And what else do we have? We have an image array, right? We have a user image array and it's going to be a string right now because we're only getting the URL strings from the server. And again, I believe we are done here. So, let me go over this and just say self.appends, not append self.userEmailArray.append(postedBy). So, that's it. And I will proceed with other values in here as well. So, the next thing would be for me to run the if let one more time rather than postedBy, we may just get the post comment, okay? So, let me say if let. And remember we can do this inside of this if let as well. For just variety, I'm doing this in here. In your case, you may want to go for a nested if statements, and let's go for... Let's see postComment, okay? If let postComment is a document.get, so this one, yep, .get, and this is postComment as well with the uppercase C. I'm going to cast this optionally as string as well and then I'm going to add this to my userCommentArray, and say .append(postComment). Here you go. Now I'm going to say if let's like array or let's say likes, if let likes = document.get okay? This one .get(''likes''). I am going to cast this as an integer this time, okay? Because we have saved this as an integer, remember? So, let's go and say self.likeArray.append and it asks us to append an integer as well, so I'm going to say likes. And finally, we have the imageArray as well, right? So, let's do that. I'm going to say if let imageArray, not image array, if let image = document... Let's say imageUrl because it's not image, it's just an image URL, okay? Say document.get(''imageUrl'') as? String. So, I'm going to append this to my string area as well. Use your ImageArray.append(image.Url). After we're done with this for loop, I'm going to call my TableView and reload the data. So, I'm going to refresh my TableView as usual. So, say self.tableView.reloadData, okay? And after doing that, this information will get reflected to the TableView so that we can see them on our TableView. So, far so good, in order to show those information to the user, I believe you have to do one last thing and that's changing this number of rows in section and make this one equal to userEmailArray.count, okay? And in here rather than saying firstname.lastname@example.org, let's say userEmailArray[indexPath.row]. And this will take everything from the userEmailArray and display to the user. So, for like label, I'm going to go for likeArray, yep. This one likeArray[indexPath.row]. And, of course, this will give me an integer and that's not what I want because I want a text. So, let me convert this to be a string. And then later on, I'm going to go for comment as well. And this is going to give me a string, so I don't have to do anything. So, userCommentArray[indexPath.row]. And later on we have to find a way to download images from the URLs and show it inside of our ImageView, but I'm going to skip it for right now, we're going to do that in the next lecture. So, let's test all the other information and run this. And as you can see, we only have two values. We have two posts. So, we have my favorite comment test to like button, like count and everything in here. So far so good, we only are missing the image right now. So, we have to come up with a way to download those images and show them to the user in our ImageViews. So, that's exactly what we're going to do within the next lecture.
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.