Getting Started with Vapor 4 Lesson 3

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
In this video, I'll show you how to create a Swift UI app that uses our custom Vapor back end API to read and write data to a database. Hey, everyone. My name is Mikaela Karen. I'm a full time iOS developer, and recently I've been learning Vapor, so I'm excited to share with you how you can use Vapor to make your own API back end. Okay. Now let's create the iOS application. So just go to Xcode and do file new project. Then here make sure you select iOS and then click on app and we will call this YT Vaporios app and we will change this. So it is in Swift UI and this is Xcode 13. So this is what it looks like. You don't have to select lifecycle. I don't think anymore. So this is that and then click on next. But go ahead and find where you want to save your project and click on create. Okay. Our project is created. Let's go ahead and run it. We're just going to use the simulator rather than my phone. So we have created our project and then we built it for the first time. So we know everything's working. I'll keep that up and we can turn on the preview. I don't use it that often, but we can put it there. But let's go ahead and make our file structure. So we will be using MVVM, which is model view view model. So let's go ahead. Right click here and click on new group. So we have models. Come on. We have view models. I don't know why mine's doing that. Mvv and the models view models. And I like to put these in alphabetical order just because I think it's easier. So move that one up here and we'll also create one called utilities. And then I'll put that one down below. Okay, first thing we are going to do is change the content view. Instead of being called content view. We're going to call it song list. So we right click on that and click on refactor and rename. You want to click the plus here. So it renames the comma itself and you can see it's going to rename the file too. So now we have a song list and then let's go ahead and drop this into the views. Just expand all these. And first thing we need to do is create our model because we have to model our data somehow. So we do file new file. We want to make a Swift file. Okay. Let's call this song and create a structure for the song that we made in our API project. We will make it conformed to identifiable and codable. So the codeable so we can decode and encode everything and identifiable is because it has an ID and we will be using a list in Swift UI. There we go. So that will go away because it now conforms because we have an ID property. Okay, let's make our song list. Open up song list here. Maybe one day the preview will work, but let's go ahead and make the list. So we wrap it in a navigation view, make our list, and then we need our data to be represented somehow like an array. So let's go ahead and also have a view model for this. So we right click View models new file on a Swift file, and I will call it Song List view model. Make sure that is checked down here. Click Create. Let's go ahead and create just an array in here. So we have just our songs array and it's an empty array and it's a published value. So if we go back here to song list, we have our view model. Is this ever going to build? Oh my goodness. Okay, we are making a list and we want to iterate through all the objects within our songs array inside of our view model. So let's type A for each loop and I will make this smaller inside of our list. We are going to have just instead of a label. We're just going to use a button because we will make it so you can tap on every row. And I just have the text as the song's title. And then we set this to font three, and then the foreground color is label, which is a systematic color. So when it switches from light mode to dark mode, it'll automatically switch and we don't have to manually say what the color should be, and we will add a navigation title as well. So we don't see any data because we don't have any in the preview. Okay, so let's fetch some data from our API. So in our view model, we will need a way to get that data. Let's create a function called fetchsongs. Okay, so we will be using async await for this, which is only available. So right here you can see concurrency is only available in 150 or newer. So let's open the side panel back up again. So I did that with command zero and click on our project and let's set the minimum target to 150. So we don't get that warning. So 150 right there when that target is selected and then make sure it says 150 for that one as well. You can see these two different targets, rolled the target in the project and there we go. So reset that and save it. Close this. And if we build project again, this little warning should go away. Okay, our project says build succeeded. So we're good. And then that warning doesn't come up anymore. To fetch our data, we first need to say what URL it's coming from. So in our API we had URL was 127 one, but that's not really a real address. That is just the name of our computer, which is also called localhost. But everybody's computer is called localhost, so we can't just hit that URL. So we'll solve that in just a second. But before we do that, let's first create the code that will actually go about fetching the data. So what we're going to be doing is making a single ten called http client. So go ahead and click on utilities and create another new file. I'll make it a Swift file. Write http client and hit. Okay, so this is what makes it a single ten. We don't have an initializer so you can't initialize this object, but we can access it through this shared property that we created. And then that is what accesses all the different properties and functions. So we want to fetch data. Let's go ahead and make a function called fetch. As you can see, this is a generic function. So what we are going to be doing is making our http client generic, so that really it could be adopted. You could copy this code and drop it into any project that you have that makes http request. So the generic means this is the value or the property that we're using called tea, and it just needs to conform to codable. And then what we return is our object, which is an array of T objects. And for us it will be the song model. But again, you could drop this code into any project and it would work. So how do we do this with async await? We first need to make the request for fetching data. So this is the async version of the shared data task. And when we use async await, because this is an asynchronous function, we have to have the await in front of it. Meaning wait for this to finish. And don't worry about this. It'll go away in just a minute. And here we are going to check that our response first is an http URL response. And then this property or type has a property on it called status code. And we want to make sure that's 200 because 200 means it was a good response. And then we are going to throw an error. So first let's make the kinds of errors that we'll be throwing. Put that right up here. So these are different types of errors. So if we get to this point, we know that it was a bad response back if it was anything other than 200, and now we need to decode the data and put it into whatever type T is. Here. We have an object and we are going to decode it using a JSON decoder, and it will be of type T, and it's an array of those objects. And we are decoding the data that is right there. And then if that doesn't work, we will throw the error decoding data, and then we will return the object. So that's what's returned out of this. So let's go ahead and build the project. Okay. If we build the project, it succeeds right here. I had accidentally Typed data, not data or I type data task rather than data. So this is the asynchronous one and you can tell when you command click on it and it goes to QuickHelp. You can see it has the word async in it, and it tells you it retrieves content from our URL and delivers the data asynchronously and that's exactly what we want. So how do we go about using this function? We're going to be using it inside of our song list view model to fetch objects. So the first thing we need to do is define our URL. So to do that, you're going to create a Constance file. So this URL won't really ever change. It is going to change when we are doing the development work. But the actual URL that ends up being deployed in the final video. It won't change. So let's go ahead and make a constants file for that. So we create a new file in our utilities folder. Create constants Swift, and I like to put these in alphabetical order sometimes, and we will create an enum, so it will look like this. We will fill in the rest of this in just a minute. But for now, this is all we need. And let's also create an enum. So this is our endpoints. We only have one because we're only reading and writing to that one songs endpoint. So we just call the songs and in doing it like this, making enum with a static variable, which is actually constant, but it's still a variable. But the static variable allows us to use this in a type safe way. So in case we ever accidentally wrote song instead of song, every time you type this endpoint, you basically won't be able to do that with this endpoint or with this object because it will be completely Typesafe. So let's go here and see how we do that. Let's create a URL. So this is just a string. So we have constants baseurl so that's the URL we will fill in right here and then plus endpointsongpoints songs, and we will put a slash at this. So it'll be something like it will look something like this actually. So this is what is called the base URL, and then the endpoints are slash whatever as after this. So if we go here. Yeah, that's fine. This is just telling us that we haven't used this variable yet. So it wants to put an underscore, but we will use it. This is a string too. So let's create the actual URL object itself here. We have a guard because we want to make sure that this URL is for sure a value and that it doesn't throw, because if you look at the signature of this function, that's just the structure actual function. Can we go to that? Open up the developer Doc. Oh yeah, that's just initializing in the URL, but it does throw right here. It creates a URL instance but with the question Mark means it might be optional. So that means if it can't create a URL, then the value would be nil here. If there's any illegal characters, it would be nil. So using Guard, we want to make sure that this definitely has a value in it. Otherwise we want to throw the error bad URL. So let's use this. We will create a variable called Song response. So this is how we use our async await function. So here's our Singleton http client shared, and we are using this fetch function, and we're passing in the URL that we created right here. And what's returned from this is an array right here. It said an array of T. But with this we are specifically saying it'll be an array of song objects. And once we have all of our song objects, we want to set that into our variable right there. We have to do this on the main queue because that will update this variable. And with Swift UI it will know to refresh the view. So this is something that must happen on the main thread and then that's it. So we can go ahead and build the project and everything should build. But we can't actually reach our data just yet from our API because for one, we don't have a URL filled in. Okay, we have built succeeded, and we don't have a real URL here. Let's first CD into our API project. So this is what mine is called it's the Ytvaper API, and this is just the branch name. If you saw this before, I broke up all of the files of the project into different branches. So you can look at a specific branch to see all the code for that specific lesson rather than having multiple repositories for each lesson. And we need to run our database. We need to run our database with Docker. Okay, the first thing we need to do is we need to run our database with Docker and we need to run our API so we could write Docker, compose up DB and run it from the command line. Or the other way is we can use the Docker desktop application. So if you open up the container that we have here and that is the database, you can just hit play or start. Okay, we have it up and running. And if we just click on this row, we'll see the same kind of output that came in when we were on terminal. So this is just another way to run the Docker container. So we have our database running right now, but we need to run our project. We could go ahead and run it via Xcode, or we can just run it on the terminal as well. So if you type the command vapor run and hit enter that is building our project and running it so that will build our project and run it all in the terminal rather than running it in Xcode and you can see it's going and fetching all of those different packages that we have. And this is the first time I'm running it through terminal, so this may take a while and it's already in use. Okay. Mine came up with that error again. That address is already in use. So we need to fix that by running the command lsof I 80 80 and we can see postman is using that. But that one killed postman last time. So let's use this PID. So kill nine. Then the PID number hit enter and then else off and that's gotten now. So let's type vapor, run enter and then now the project should try to build again and run all in the terminal rather than running it from Xcode. We wait again. Okay. Cool. So everything worked. But again, we cannot hit 127 one at because everybody's computer will say that. So it's literally not possible. That's just what the computer is called. So the URL we are going to use, we need to open up a new terminal tab so we can't use this URL. But we do need this actually up and running because this is our API, and basically it's like it's on right now. But we need something to bridge the gap from the iOS app to go to our API. So for that, we need a new tool that I forgot to download initially called In Grok. So it says it right here public URLs for exposing your web URL or whatever that said for exposing your computer. So go ahead and just click on this download button. You don't actually need to sign up for an account, even though it does tell you to do that. Just click on download and it will download a file called In Grok for you. So I don't follow this. I tried to and it did not work on my computer to unzip it. And again, we don't have to create an account either. We can kind of just use it immediately. Okay. So once we have that downloaded, open up our new tab and terminal. Just typing CD and hitting enter will give us our root directory, and mine went to the downloads folder. So when we type LS, we see our file called Ingrock sitting here. So to use it, we do ingrocks, we type ingrock http. 80. 80. So what we're going to be doing is like opening a Port on our computer, and this is the Port that we want to use, which is the one that our API is using. So when we hit enter on this, we can see it brings up this window here is like this word forwarding and this URL right here. So make sure to grab the one that's Https and you can see this URL will reroute to localhost 80. 80, which 1270 one is the same thing as localhost. So for the URL in our constants file, we want to put the same thing and don't forget to have the slash right there. So when we hit our API and it says right there too, when we hit the API, we'll use this URL, which that will go to in grocery in groceries. That then that will forward to our personal computer that says localhost 8080. So let's go ahead and run the iOS project. Okay. And we can see nothing happened. The reason for that is because we never called our function. So you have to call the function for the function to actually work. And you see this output right here about the navigation title. This is some just weird thing with Swift UI. It has all these constraint errors for this title. So if you remove that, that'll go away. But again, we need to call our function Fetch fetchsongs for it to actually go out and fetch new songs. So if we go back to our song list, we want to add a modifier to our navigation view. So I'm going to close this so you can either grab it right here and swipe it away or click on this button and it hides and shows the canvas. So we want to add a modifier to the navigation view called on up here. And from here we want to call our function in the ViewModel called Fetch songs, so we can't just call it directly like this because we will get an error telling us, come back here. There it is. We will get an error first telling us we need this is an async function, and this function doesn't support concurrency. So it's on a peer function that doesn't inherently use concurrency. Also, there's like four errors on this. And then the other thing is telling us this can throw and it's not marked with a try. So if we look at the function here for one, it is async and two the function actually throws. So right here it would throw an error. So when we use throws, we need the keyword try in front of it, and then we have the other keyword await, which goes hand in hand with using Async await. That's the pattern for concurrency code. And then this is the error that's again telling us that the function does not inherently use asynchronous code like we haven't written right here. So to fix that, we can put this inside of a new task, and this task is asynchronous. So if we look at the quick help for here a unit of Asynchronous work. So now if we build the project, this should build and be fine with command B and there we have build succeeded. But this function can still throw an error, and we kind of don't handle that immediately right here. So let's wrap this in a do catch block. Okay, we have wrapped our ViewModel fetchsongs inside of this do catch block. So in case this ends up throwing an error instead of doing nothing with it, we will print out the error. So this is just printing the word error. And then this is the error that's actually caught that's thrown from this function. And then I use emojis in my code a lot. Just because it helps you see everything in the debug log down here, especially when you have all this constraint kind of stuff. You can just throw in an emoji and then see it very quickly. Now that we have that we still have this running and you can see it only says an hour and 54 minutes left. So after that time is over. This URL doesn't work anymore. So that's why we can use it for development. But that's not what you end up using. Long term. Let's run our project now and we should see it actually going and fetching the data from our database, which is just that single row of data. I believe the songs is money. Yes. Okay. The project built and we can see on the right. We have our one thing. The database that says money. So we have two outputs down here. The first one is in Grok. We can see that we did a get request to our songs endpoint, and it came back with 200. Okay. And if we look at the vapor output when we did vapor run, we can see almost the same thing that we did a get request to the slashsongs endpoint, and that's about it. We don't actually see that it said 200, but we know that it worked because the data shows up here and we didn't get an error thrown. So now that we can see data, let's add new data to our database, but through the iOS app, let's stop the project and we can leave this running right now. So we want to add a new project by tapping a button in the top right in the navigation bar. So let's add that with a toolbar. So we add this to the list property here rather than to the navigation view. Okay. So right here we want to have a label called Ad Song. So if we look at this actually, we could try to look it in the canvas, see if it works. My canvas doesn't work. Usually it struggles a little bit as opposed to running the app all the time in the simulator, because I do UI kit way more than I do Swift UI still. And so I'm still used to just always running it in the simulator. My computer is a little slow, so sometimes works sometimes doesn't. But we should have a button in the top. Right. That is just the system image of Plus Circle. So system image that is from here. So there's an app called SF Symbols, and you can go and download that. I will have the link in the description below, and we would use the one I Typed Plus here and you have all of these different images that you can use. So if you right click it and then I don't know why we can't copy, but the image name is whatever's down here I'm using Plus Circle, which is somewhere around here. I found it earlier, but you can use one of these as system images in your code, and then these are just a ton of ones that Apple just gives you. So we are using Plus Circle, and I used a label rather than just an image with a system name because this is more accessible. So if somebody was using voice over, this would say Add song instead of just the words plus circle on it. And then you can see the database was hit a couple more times when we were running this preview, but when we click the plus, we want a modal sheet to come up. So let's build that part of it. So we are going to use the dot sheet modifier and put that on the navigation view. So let's put it right here before on appear. So an action sheet is what comes up where it has those options at the bottom. But we just want to use a normal sheet. I'm not sure why my Xcode doesn't remember what that is. We are going to be using this one that says binding identifiable rather than just presented, which is just a boolean because the sheet that we're using, we will use this sheet for both adding and updating values. So we need a variable that we'll use here and we do want to do something for the on dismiss. So first before we fill any of this out, what variable are we going to bind to? We are going to make a newenum type. So let's click plus and then new file and utilities and it will be a switch file called modal type. Okay, we have created a new enum that conforms to identifiable. So in order to conform to identifiable, it needs to have an ID. So here we are just creating a computer property and switching on ourself depending on if the case is add or update, we are just returning the ID of a string just called add or update. Then our two cases are add and update and update has an associated value of type song. We'll see about using that later. So for now we have our modal type. So inside of our view model or sorry, no inside of song list, we need to have a variable right here that we'll be using. So we create a new variable called modal, and it's a type modal type and we will set it by default is nil because no sheet will be showing. And then that's because we haven't Typed anything here we type modal because that's the variable that we want to use. We will fill that in a little bit later. And for content, I don't like the way it looks right here. So we will take off just by default. I don't like what the autocomplete does, so we will take off that part. This is the content part of that closure. I just didn't like the way the auto completes to look like that. And what we're doing right now this doesn't work because we need to fill something in. But what we are doing right now is we have our modal type and then we were switching on what that modal is whether ad or update was selected and we want to show a different view. So we haven't actually created that yet. So let's go ahead and do that. So let's create a new view and it will be a Swift UI view. Let's call it add update song. Inside of this, we can do two things. We'll either be adding a new song or we will be updating a song. So what will we be displaying? We are going to just put a V stack on the screen that will have a text field property so we can type something and it will have a button. So our ad update song also needs its own view model that we will use to fill in some of these things here. So let's create that view model. Now do command n on our view models using a Swift file. Add updatesong ViewModel and our view model will conform to Observable object because it will be a view model. We'll wrap it in a property wrapper on the view, but the first thing we need is a published property and it will be an empty string. So that's what we will use for a text field over here. Okay. So we have our view model and it has a property called song title. And then this is what's shown in the text field before we type anything and it will just say song title. So on this will add a little bit of styling, so it doesn't look weird. So here at the text field style will be a rounded border, so that will literally just put like a Gray border around it and then add some padding so it's not right up against the side. Let's fix this down here by just creating a new view model. But what do we want our button to say? So our button is either going to say add or it's going to say update, depending on what this modal is doing, which will happen over here. Okay, so let's first make our view model, so we will make the view model. It's going to have a couple of properties on it, which will be a Uuid. So the song ID. This will have a song ID if it's the update, meaning we're passing the song over to this view and it won't have a song ID if we're adding a new song because we haven't Typed anything in there yet. So we'll use the property VAR is updating to know whether or not this view is in the updating state or if it's in the ad state. So when we type song ID is not equal to nil. Well, if the song ID is not nil, then that means we are updating. So is updating would be true. And then vice versa. And then I talked about over here. We don't know what we're going to write for the title of our button if it's going to say add or update song. So we'll create another computer property for that. So here we have. We're checking again. If the song ID is not equal to nil, if it's not nil, then we will say update song. We are using a ternary operator here. So then if this statement is false, we'll say Add song so button title. We can then copy this and put that in as text right here. Let's create a blank initializer and we will also have an initializer. And then we have another initializer with our current song. There we go. We have another initializer that says that Intake is a current song and we set the two properties song ID and song title. But if we don't have a current song, that means we're adding a new one. So right here it doesn't take any properties, and this is fine to do, because every property we have in here will have a default value of some sort. So this one is an empty string. That one would be nil. This one could be true or false depending on that. And then again, this one is one of those two values. So we want to add a new song. So let's create a function to do that. And the code for adding a song is going to look very similar to the code that we just wrote for fetching a song, and we can actually go and probably copy a majority of this. So we can copy this part because we'll be doing the same thing. We have to create our URL, and then we will use the base URL from constants and we're using the same song endpoint. But what we are doing is we are sending a song to the database to the API, so we have to create that song property. So here what we're doing is creating our new song. It does not have an ID yet because we don't assign one within the iOS app, and then we're using the song title. So that is whatever ended up being Typed into the text field in the view. Now we need to actually make the URL. We need to make the URL request, so we don't do that here. We do that inside of our Http client. So we have to make a new function because we're not fetching data. We are sending data. So we'll make a new function called send data. We will close that there so we can see the whole line. So because we're using generics. Again, we have our type T, which conforms to codeable. There we go. And then we are sending it to this URL. I cannot type object. The object that we're using is of type T and then Http method, which we'll look into, and then that will be a string. So the first thing we do is we have a couple of Http methods. So we have seen two so far. We saw get and then post. So let's define those up here. And again, this is all to make it type safe. So in case we accidentally spell post wrong, it won't break all of our code. So this is an enum with a raw value. So we've used post and get and we have not yet used put and delete, but we will get to those. And then with the raw value of string, the raw value will just be the case itself. We also need to add a few other things, and this goes with the URL request. So we'll look at these a little bit later when we kind of see it more in postman or I can open that now too. I already have that. So in postman when we did a create song, when we added a new song, we didn't look at these headers. But this is what we're doing right here. So that said http header. So we added by default, it adds a header called content type, and we set it to applicationjson. So that's what these two things are used for. And then that basically just tells the request what kind of data are we sending over? Let's go down to send data and make our URL request. So here we are making our request. And what we saw in postman, I forgot to add the actual name URL here. So what we added was this is the applicationjson part of the header. And then this tells you for header field and the field was content type. So we see the same thing in postman. The key in value, which is sort of the same thing is content type. And then we have application JSON. Everything else are like defaults. So that's why it says auto generated headers. So we've added that to tell what kind of data we're looking tell the request what kind of data we're looking for. I'm just going to enter there to make this a little shorter. And lastly, we have to send the data along. So we want to send data to our server. So here we have an HTT body and we want to encode our data from our object, and then we encode it as JSON. So that's why when we went to send data, we had the body property, and then this is our JSON object with a key of title, and then the value of money. And right here we're telling it it's JSON. Now we actually need to make the request. So here we are doing the exact same thing as we did at this part inside of the fetch function. So this is the same thing. Except we are passing a request rather than passing a URL. We put an underscore here because we don't really care about the data that's coming back because we don't actually have any data coming back. We are responding to the request with just a response. So that's what this value is. And then for those of you who don't know this is a tuple or tuple, I don't really know how it's pronounced. And it allows you to kind of have two values that are returned out of a function rather than just returning a single value. This is like a comma separated list of values. So we have data and response. And then again, we are checking the response that it is of this type and the status code is 200, because if it's not 200, that means that it didn't go okay, or it didn't go well and it failed. So now that we've created our Http client, now let's go and use the client in our view model here. So what do we want to send. We want to send the URL. You can see it says encodeable and decotable by default, because right here we say that T is of type codable, and if you click on this and click help. So command click on. This. Codable is actually a type alias for decotable and encodeable. So we want to pass our object of song and http method that we want to use instead of just typing post directly here we will use our enum and use the post and raw value. So I'm going to hit enter on this just to make it easier to read. And then that's all we have to do to add a new song. So now we need to call our add song function. But to do that, we can't just call that directly in our button. We could for now, which I might do. Actually, it's part of the ViewModel. So we need ViewModel add song. We cannot just call ViewModel add song. We could, but we're using this for both add and update. So we kind of have to have something here that decides are we adding or updating depending on that, we perform the right action. So inside of our view model, this is part of the view model. There we go. That one error should go away, but we have add updates song. So we have adding a song. But yeah, we need to decide are we adding or updating? So here again we're calling this and it's an async function. So we need to put it inside of a task. So how do we decide if we're adding or updating? We created a property up here called is updating, and we can use that in our if statement. And by default if you don't type anything like equal equal true by default, it says if this is equal to true, which is the best way when using booleance. So if we are updating, if that's true, we want to update this on, but we haven't done anything here. So let's put a comment updatesong function else we want to call our function add song. And again, this is an async thing that throws. So we actually need to put try a wait on top of it or before it. And we want to handle what happens. So we want to put all of this inside of a do catch block. So when this function, if there were to be an error, we want the function to throw and actually handle the error as opposed to having it just sort of disappear. So here we do that. And then I added a completion handler on here because after everything has been performed. So we go to right before the end of our task. I want to call our completion handler because when we call this function, when we add something new to our database, we want to wait until this action completes before we do something else. Like updating our view for updating the new song in our list. We have all of this here. So now we can call this inside of our button. So we have our add update action. After we have done the action of adding or updating, we want to close the view, which is one thing. So to do that, we first need to add an environment variable, and this is how we can dismiss this view after our song has been added. So once we do that, we can go back to song list, and now we can call the right thing here. So when we're right here we want to show add update song. So here now we're presenting the same view. Except when we do add song, we give a view model with nothing inside of it because there is not a song yet. Whereas when we do update song, we are using this variable of song to then pass to the view model so it knows what song we are then going to update. And we have this on dismiss code here because at the point of after we have presented the modal type something in clicked on the button. The view is then dismissed and we want to then update our view here to show the new song inside of that list. Let's do that with our function of fetch. Okay, so we have ran the function inside of our task block because this is an async await function or it's an asynchronous function and we are calling ViewModel fetchsongstfetchnewsongs after the sheet has dismissed to get updates from our database. Then we put this inside of a do catch again to handle the error if it comes back. So we built the app and ran it. So now we should be able to click on run and we should be able to type in new songs to add to our database and also read all the songs from the database. Bad access. What is that about? So I'm going to clean the project and then build it again because I'm not sure why that came up. So you clean your project with commandshiftk. Okay, our project built and we can see that we have a new request here through the songs endpoint because that's what runs when we load it for the first time in this dot on appear. Let's click on the plus and I did not connect it because you need to call the function and not just print add song. Where did I do that? Right here. So we want to type modal equals add because our sheet is bound to this modal property. And when we click on add song, we want it to present the ad sheet, not the update one. So let's stop it and run it again and we see a new request here for the songs endpoint and we see a new one right here because that's what we did when we got all the songs. Now we click on the plus here and we see our modal pop up with the text field on the button. So what song do we want to add? Let's add as brothers. So if we type that and click on Add, we saw the modal go away and we saw our data update right here. You can see in our logs. We did get songs first or that wasn't the first thing. Yeah, it was. We did get songs when the view loaded for the very first time. We did a post to create our new song, and then we did get songs again so that we can update our initial list. And there we go. We have successfully created new items and put that in the database. And also we have read data from the database to view in our iOS app. So to stop everything, we can stop the project and to get out of this, you type Control C to stop our Vapor API from running, and then to stop in Grok from running. You type Control C as well, and it'll just go back to your downloads folder. That was a lot of code. What we did was create our folder structure using MVVM model ViewModel. We created network Request using the new Async Await syntax with Swift 5.5 and we made it generic so that we could drop this code into any other project that we wanted to that uses network requests. Lastly, we used in Grok to connect our iOS app to our local Vapor API. If you like this video, be sure to give it a thumbs up below and leave any comments. If you have any suggestions on how I can make these videos better, see everyone in the next video. When we learn how to update and delete data from our database.
Info
Channel: CodeWithChris
Views: 3,933
Rating: undefined out of 5
Keywords: swift vapor tutorial, vapor swift, server side swift, server-side swift tutorial, server-side swift 2021, server-side swift vapor, vapor swift tutorial, vapor tutorial, vapor 4 swift, server-side swift with vapor, swift vapor routing, vapor 4, swift rest api server, swift server-side framework, build a rest api, swift vapor
Id: TyigCzPoLak
Channel Id: undefined
Length: 59min 53sec (3593 seconds)
Published: Wed Nov 03 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.