How To Build a YouTube API Video Player App | Chris Ching | Skillshare

Playback Speed


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

How To Build a YouTube API Video Player App

teacher avatar Chris Ching, Co-Founder of CodeWithChris.com

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

    • 1.

      Lesson 01: Exploring the YouTube Data API

      17:53

    • 2.

      Lesson 02: Getting Data from the YouTube API

      32:48

    • 3.

      Lesson 03: Creating the Xcode project, views and models

      9:01

    • 4.

      Lesson 04: Sending the API Request

      29:22

    • 5.

      Lesson 05: Parsing the JSON data into Videos

      13:00

    • 6.

      Lesson 06: Retrieving Video Thumbnails and Styling

      8:46

    • 7.

      Lesson 07: Video Player and Video Detail View

      18:25

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

61

Students

--

Project

About This Class

In this class, you'll learn how to build a YouTube Video Player iOS app using SwiftUI!

The app will fetch videos from the YouTube Data API and users can watch the videos right in the app!

What You Will Learn:

By the end of this class, you'll be able to:

  • Work with APIs in Swift
  • Store your API key securely in your Xcode project
  • Understand iOS networking using async and await
  • Make network requests to URLs
  • Download images asynchronously
  • Use Swift Package Manager to add third party libraries to your Xcode project
  • Use a TabView in SwiftUI
  • Use a ScrollView in SwiftUI
  • Display slide up views in response to user interaction

Why You Should Take This Class:

The skills taught in this class are highly transferrable to your future apps.

Being able to work with APIs opens up many possibilities for different apps you can build1

Who This Class is For:

This class is not for beginners. 

  • You should know how to use Xcode
  • You should know basic Swift syntax
  • You should know basic SwiftUI components

If you're just starting on your iOS journey, please check out my other beginner classes to learn these skills first.

Materials/Resources:

As with all iOS development, you'll need a Mac computer to run Xcode.

Xcode is free and it's where we write the code and build the views for our app.

Accessing the YouTube Data API is also free.

Meet Your Teacher

Teacher Profile Image

Chris Ching

Co-Founder of CodeWithChris.com

Teacher

If you’re a beginner and you want to learn app development step by step, in plain simple terms, then you’ve come to the right place.

Thousands of people, just like you, have used my actionable video and article tutorials to go from a beginner to a full fledged iOS developer.

What makes CodeWithChris different is the focus on staying motivated through small gains while building momentum to get to the finish line and cross the “Hump”.

My effective and motivational approach is why thousands of beginners are finding success using my material.

If you’d like to learn more, join my Skillshare class, visit CodeWithChris.com or search for CodeWithChris on YouTube.

See full profile

Level: Intermediate

Class Ratings

Expectations Met?
    Exceeded!
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Lesson 01: Exploring the YouTube Data API: My name is Chris, and I'm going to show you how to build this IOS app that displays videos from YouTube. Now, here's what the app looks like. You can configure the app either to show individual videos or all the videos from a playlist. Now, the data is being fetched through the YouTube data API. So if you modify the play list by adding or removing videos, it'll automatically be reflected in the app without having you revise any code. Oh, and you can tap into the videos to watch it as well or read the video description. Alright, now let's take a look at what skills you'll gain after completing this app. After completing this app, you're going to get experience working with the YouTube data API. You're going to also learn how to send and receive network requests from the app. In doing so, you're going to learn a little bit about IOS concurrency, especially using A Sync Wait. And you're going to learn how to debug network traffic using Pxy Man, which is a free third party tool. And that's going to allow you to troubleshoot anything that goes wrong when you're making your network calls. And then when we get the data back from the UTube API, we need to turn it into something usable in our app. So that's where you're going to learn about JSON parsing. We're going to need to store our API key securely in our X code project so that doesn't accidentally get leaked out. You're going to learn how to do that. And as for the app side, you're going to learn how to play UTube videos in your IOS app. We're going to use a third party library called UTube Player Kit, and we're going to integrate that library into XCode using Swift Package Manager. Then you're going to learn some swift DUI things such as using lists, geometry reader, a sync image, progress view, scroll views, just to name a few, and a lot more, just in terms of building user interfaces and capturing user interaction. Let's do a quick little overview of how this all works in case you're new to working with APIs. If you have used the APIs before, then this will just be a little review for you. Now an API is an interface that you can connect to to send and receive data. To put it in simpler terms, you can think of an API as a collection of URLs that your app can access to retrieve data or to send data. Now there are many APIs out there. Some are free and some are paid. But most of the large platforms like Facebook, X Spotify Google, they all have APIs for you to work with that platform or to retrieve data from it. There are some APIs that are just data focused, such as retrieving recipes or stock prices or weather data, things like that. Being able to use APIs in your app is very, very powerful. What actually happens and how do you use an API from your app? Well, from your IOS app, you send a network request to an API endpoint, which remember is just a URL. In your network request, you specify what data you want to get back. In some APIs, you also have to identify yourself in the request. This identification part is called authentication. The API receives your request and it will authenticate you and also make sure that your request is valid. Note that not all APIs require authentication, but most do. Now, if your authentication checks out and your request is valid, then the API will go ahead and gather the data and send a response to your app. The response contains the data that you requested, and it's typically in a format called JSN. When your app receives the response, it can read the JSN formatted data and then convert it into data that can be displayed on the screen for the user to see. This process of converting the JSN data into usable data in your app, this is called JSN parsing. All right. This is the process that you're going to learn how to do with the YouTube API. Now let's take a look at the YouTube API. Here we are the YouTube Data API. You can visit this page at developers.google.com slash YouTube. I want you to go under this section that says Add YouTube data and click references. And here you can see all of the endpoints that are available in this API for our app to send a request to. Now, remember, these endpoints, they're just URLs. So let's take for instance, search. Let's look at overview first. This describes to you what this endpoint does, how you interact with it, and it lists different methods, different ways you can use this endpoint. So let's take a look at list. When you click into that, you see that change to this section here and the common use cases. This is essentially searching YouTube for something. You can search here some use cases by keyword, which is probably the typical example. Location live events or your videos, for instance. If you scroll a little lower, this is the important part here. This is telling you the exact URL that you need to hit. This is the endpoint, and this is the request type. When you send a network request, it can be one of A couple a few different types, and get is the one that is typically used for when you want to retrieve data from the API. Not only do you need to send a request to this URL, but you need to specify parameters of your request. Remember. If you're searching for something on YouTube, what are you searching for? You can't just say search. Here, these parameters, they describe what you can specify along with your request in order to tell the API what you want to retrieve or what you're searching for in this case. Let's take a look here. One thing I should mention here is in the parameter section, there's not always, but there may be required parameters. Remember, in that overview, I said that the API checks your request to see if it's valid. Well, if it is a required parameter, then you have to specify this information. Optional ones, you can leave out, but the required ones, you have to include as part of your request. What is this required parameter? This part, it's called part. This parameter specifies a comma separated list of one or more search resource properties that the API response will include, set the parameter value to snip it. So It's a little hard to determine what these things mean. But what I'll typically say is to try it out. The next step is to track this API, let's set this parameter to snip it as it says, and then let's see what gets returned. And if it's not what we're looking for, we can probably look at what else we can specify for this parameter. Now what I'm looking for is, if we want to search for something specific, like a keyword, where would we do that or what would we do? This is searching by location. This is searching by event. This is searching for types of channel. Specific channel you can look for how many results you want. This is the one. The Qe parameter specifies the query term to search for. If you wanted to search for videos regarding, let's say, gardening, you would put the gardening keyword in this parameter. I'll show you a little later how you assign that data to these parameters, but we're not going to dive that deep. Just wanted to give you an overview of the YouTube API and all the endpoints that are available. And also how these endpoints work. You learned about the URL, this is the URL that you're going to send the request to. This is your request type, and there are required parameters that you have to specify, and there are optional ones that would give more context for your request. Now, the endpoint that we are going to use in this video series, Um, remember, this app, it can display any YouTube video, and it can play it in the app. So for my use case, I want to display a list of videos from a specific playlist because I have a YouTube channel, and I have some play lists that I want to display the videos for. So the endpoint that I'm going to use is play lists here, and I'm going to use Actually, I believe it was I can't remember if it was playlist or videos at this point. Okay. So let's take a look at this endpoint. So here is the play list endpoint, get. And if we take a look at the use case, let's see. It retrieves all playlists or yeah, all playlists for a channel. That's not what I want. This one is, let's see. The request that I use retrieves a specific play list, and I believe it was this endpoint, because there is, let's see, the ID specifies that we're being retrieved. Yeah. This is what I used. So instead of retrieving all play lists from the channel, I wanted a specific one. So I had to include this parameter here, which was called ID, and this is the ID of the specific playlist that I want. And then within that play list, I also got the videos. After you complete this video series and you follow along and you learn how to use this YouTube data API, feel free to change the way that the app works. You can implement search in your app if you'd want. Just put a text field, when the user types something in, call this call this endpoint. Pass in the keyword that the user search for and return a list of video results, and the user can play it right in the app. What I'm going to show you in the video series is using this end point, showing a specific list of videos. Or you can curate your own playlist or maybe curate specific videos that you want to show, and you might use another endpoint. So feel free to customize the app. But I would recommend, especially if you're new to working with APIs and networking, to follow along in this video series, wait till the end, get comfortable after you've achieved the result, and then customize it. Now let's take a look at authentication because this YouTube data API needs to identify who you are, before it's going to give up its data. Now, before I show you the YouTube authentication part, I want to point out this line right here. These end points, they all have a quota impact and tells you how much it costs to send a request and to get a response from this endpoint, and that has everything to do with the authentication stuff. Now let's move on to there. Now we're going to click on Guides. Typically with API documentation, all the authentication stuff is all the way at the beginning. Here, it tells you how to do that. Let's go into overview. Actually, let's go into get th credentials here, you'll see that there are two different types, two different techniques that you can go about this. One is OOF and one is API keys. Now, most APIs will use one or the other, and sometimes both. But if I were to throw out a number out there, I would say 90% of APIs, you can use API Keys. Let me explain briefly the difference between the two. API key authentication is where you sign up for an account, and they give you a long string of letters and numbers, that is your key. When you're making network requests to the API, you're going to specify that key with your request and that way, they can associate that request with your account. Then they can also rate limit you. They can see how much you're using the API, if you're abusive, if you are Yeah, mostly rate limiting, giving you quota and things like that. Because You can imagine if it's unlimited and as fast as possible and everyone is hitting their API, it could take it down or the server load could be too high. This allows them to control access to their API. If they find you to be abusive, they could ban your key, and you won't be able to make requests anymore. That's how API key authentication works. Now, OOP is a little bit different. This is where you typically see a username and password box in your app, and the user has to sign into their Google account, and by doing that, they are obtaining a token from the API. Then you attach that token to the requests that you send. So there's a distinction because now they're associating those requests with the user's Google account. So no longer are you being rate limited. It's not counting towards your quota, it's counting towards their quota. Also what you can do is different because now that Google can identify their Google account, that user can perform things like liking a video or subscribing to a video, you can call those types of endpoints. Or perhaps following a user. Whereas API Key access, all of your users, they're using the same API key, the one that that you signed up for, that's associated to your account. That's why with API keys, you can't really do things like liking a video or subscribing to a channel because the API has no idea who the user is. All they can see is that they can associate this API key to your account that you created. OOF is a little bit more involved, so we're not going to use that in this video series. We're going to go through the API Key route, and learning how to do that is going to cover the vast majority of APIs that you'll encounter. All right. So now let's go on to the next step which is actually creating an account and getting our API key. So all you have to do is follow this credentials page link, and I'm going to open it in a new tab, it's going to ask you to sign into your Google account. Because I'm already signed in, it's brought me into this credentials page of my project. You probably won't have a project either. So let me try to go back out onto the dashboard. You might have to go through some onboarding questions or something like that. But eventually, you'll arrive at a page that looks like something like this because right here it's saying I have a project, but you won't have a project. It might prompt you to create a new project. You can go ahead and do that, or you can click on this drop down up here, and then we can choose new project, and we can create a project together. Looks like I cannot create a new project. But this is what you would do. You'd type in a project name. You would I don't think this one matters too much. So you can choose whatever and just hit Create. Then once you've created a project, go ahead and navigate to that project. So for me, there would be this one right here. And you're going to click on credentials, sorry API and services, and then you're going to go down to credentials. Then once you get here, this is where you can create the API key. So you're going to say create credentials. Create API Key. It's going to generate one for you. And then you're going to have to restrict it to the YouTube data API. That would be good. Let me refresh the screen. Did it do it for me? There it is. This is the new API Key that was just created. I'm going to click into it. And then I am going to set the restrict right here. I'm going to restrict it to a specific API. The reason this is a good idea is just so that if the API Key gets into the wrong hands, I mean, it limits what they can do to just using the YouTube data API. I think it's a good practice to not just give free rein to everything. Restricting things and removing options is always good, especially if you don't need those options because it limits what limits any unexpected behavior. Same thing goes for programming, right. And I wouldn't set restrictions on that. I mean, you could do this, but it's going to get It might interfere with your testing, especially if this is your first time. So let's just choose none. Restrict the key to the YouTube data API. There's your API key right there. You shouldn't be showing this to anyone. I won't be using this key, so don't try to copy it and use this key. I'll probably delete this after. But go ahead and save it. And there you go. You have a valid key that you can use, and you're going to be using this key inside your IOS project. All right. Now we're set. All right, now we're ready to start using the YouTube data API. In the next lesson, we're going to build a test project to connect to the API and to retrieve data from it. I'll see you there. 2. Lesson 02: Getting Data from the YouTube API: In the last lesson, we went through how to connect to APIs and we reviewed the YouTube data API. We also created our API key. Now we're ready to start retrieving data from the API. Let's dive right in. All right, so let's test out getting data from this API. Now, before we get into X code to try this out, there's an even easier way that we can test out this API right from within the documentation. They have this thing called an API Explorer, and you can test out the end points right from this panel. Now, all you have to do is make sure that you're logged in to your Google account in the upper right corner. This is the same account that you created your API Key with in the Lesson one. Remember how we had to log in to our Google account and come here, create a project and then create an API Key. What's going to happen as long as you're logged into the same Google account is when you use this API Explorer, it's going to grab that API key from there and use that. So let's test out the endpoint. Now, we're actually going to use this one, Play list items endpoint. Because in the previous lesson, I talked about using the Play list endpoint, but this one actually just gives you information about the playlist itself. Play list items, this is the one we want to use. As you can see, this one, this is the URL that we have to send the request to, this is the request type, and this is the only required parameter, and you can specify different levels of detail that you want to retrieve. Now, the reason they do this is because for your purposes, you might not need all the information, and in that case, you can specify perhaps a lower level of detail, and that would save bandwidth. Why retrieve more information than you need? It's going to take longer, it's going to take more bandwidth, and so on and so forth. I've figured out that for this app, I need the thumbnail, the video ID to display the video, obviously, thumbnail to show the image. I need the title in the description. And that's about it. And Snippet is the level of detail that I need. It contains all of what I just mentioned. Now, the other parameter that I have to specify is the play list ID because I want to retrieve all the videos from a specific playlist. Now, when I first used this endpoint, I made the mistake of putting the play list ID into this parameter, but it didn't return anything, and I realized that, oh, I supposed to put it into this one. So they'll make the same mistake. Now, let me show you how you can get the ID of the play list that you want. So I've got a play list right here that I want to use, and keep in mind you can use any playlist that you want. So everything after this equal sign right here, and before any ampersand, that is the play list ID. URL might have something like this, let's say n t equals one, two, and whatever. Between the equal sign and the end sign. After list equals, that is your play list ID. Don't worry. You'll find out really quickly if it is the play list ID or not, because if you don't get any data back from this API call, then you'll know that that actually wasn't the play list ID. That's my play list ID. I'm going to copy that. Then in my API explorer, let me full screen this. Maybe I'll just make the text a little bigger so it's easier to see. Under play list ID, I'm going to paste that. I have to specify a part here. Remember, this could be content details, ID, status or snippet. Snippet is what I need. I it there. You can also see how it changes the URL that you're going to have to send a network request to. If you take a look, this might be interesting for you. This is the end point that we're sending to hit the API, send a request to. Then the data that I specified here in the parameters, it's all here. Look, P equals snippet, play list ID equals that ID, and then key equals your API key. Now there's no textbox to put in my API key here. So this is pulling from your key that you created here. That's why you have to make sure that you're logged in to the same account and because it's going to go grab it from there. I'm going to uncheck Google O Auth. I'm going to hit execute. If everything goes well, you should get a 200 response, which means that it was successful, and then you get all this data back. Now, this is the JSO formatted data that I was telling you about that comes back from the response from the YouTube API. And it's up to us to turn this data. Remember that process is called JSM parsing, to turn this JSON data into usable data within our app. You're going to see how to do that in a few lessons in the series, for sure. But for now, I just want to take a look very quickly at the data that gets returned and make sure that I have the information that I need. Here I can see that I have the title of the lesson, the description of the lesson, the thumbnails, image URLs, I have the video ID there perfect. Then this is for Lesson two and so on and so forth. I have everything. Now, if you didn't get this response, maybe you got an error or something like that. I would double check that part equals a snippet spelled correctly. I would make sure your play list ID is correct. Maybe perhaps you grabbed the wrong segment of the URL there. Then I would also make sure that I'm logged into the right Google account that has access to the APIKy. And then try it again, hit cute. Now, if this doesn't work, for some reason, you can't get it working. Don't worry, remember, this was just a quick test. The real test is to be able to do this inside X code, inside an IS app. That's what we're going to do next. Don't worry if you didn't get this part, this was a quick test of the API. We are going to now start our X code project. We're going to start a test project. This is not going to be our real app. I like to do when I'm trying new things is to just open up a new Xcode project, try something out, make sure I can get it working before I integrate it into my main project. That's what we're going to do here. We're going to create a test X code project, and we're going to try this out. Let's do it. Let's create our X code project. I am going to do this and launch a new X code project. Under IOS, let's choose the app. Let's go next. I'm going to call it test YT API. This is not our official app. It's just going to be a test. Interface is Swift GI, language is Swift, storage is none. All of this is unchecked. Let's click next. I don't need to create a Git repository. I'm just going to create this on my desktop because it'll be a throwaway project. Okay. Let us do this now. Make it a little bigger so we can see, and then what we're going to do is send that API call right when this launches from here. I want to add a task here do task and open up a pair of curly brackets. In here, we're going to make the network call and print the results. Remember, I'm not going to do things the best way. I just want to make sure that I can connect to the API from X code. Receive the right data back, right? We're testing at the API. And this is not necessarily where we would do things as well in our real project. Again, this is a test. I'll explain to you what the task is a little later. I'll connect all the dots for you. But for now, we're going to do it in this little task block. So I want you to type that out. And then let me type out some code statements and walk you through not code statements, but some comments and walk you through the steps that we're going to take. So first, we're going to define the end point URL with parameters. That's the URL that we're going to send the request to. We're going to create a URL instance. We're going to create a URL request. Instance. That's the thing that we're actually going to send, and then we are going to send the request with r session. That's a mechanism for us to do networking with. Then we are going to print out the response. We're also going to have to handle handle errors. Okay. Let's try this out now. First, let's define the end point UL with parameters. If you take a look back at the API explorer, here, you'll see that this right here contains everything we need, except we have to insert our API key right there. This is essentially the UL that we have to hit. It's already written out for us. That's what I'm going to take. Now, one thing I want to point out, which I'm not exactly sure why, if you take a look at this endpoint domain, it says Tube dot google api.com. But if you take a look at this, it's Google api.com slash YouTube. I've used both. They both work. This would probably be a little safer to use because this is in the official documentation, whereas this is in this APA explorer, maybe it's just not updated. Ah, let's just use this and then we can build it together. We can build up that URL just so you also know you have an idea of how it gets built up. I'm going to declare a constant. I call it URL string. Now, keep in mind, this is not how we are going to do it in our real project. I'm just going to write out the whole string here, including the API Key and all the parameters. So to include parameters, you put a question mark, and then from that point on, it's parameters. And then the format to specify parameters is going to be parameter name equals parameter value. What is the first one we should specify? How about part? Since part is required anyways. So we're going to type part equals, and remember you can specify one or more of these. It tells you to specify more you would put a comma in between them, but we only need snippet. I can put snippet. Now, to specify a second parameter, you put ampersand and then the same Parameter name equals parameter value format. What's the second parameter that we want to specify? That's play list ID? You have to follow it based off the capitals as well. Lower case P play list, followed by big I ID. Now equals, what is the play list ID? And pull the screen up again and I'm going to grab my ID from here. Now this actually makes sense. If you can see the URL, you can see play list, and then there's a question mark, which means parameters from now on. List is the parameter name equals, and then parameter value. Then the end of the parameter value is ampersand and then second parameter and so on and so forth. That's why I say grab everything after the equal sign, but before the Ampersand because that is just the connector for the next parameter. That's my play list ID. So Let's put it right there. I also need one more parameter. Let's put the ampersand sign, and this is key equals my API key. Now, I keep saying this because I don't want someone to watch this and say, Hey, you shouldn't just put your API key there. I know. Again, this is a test, so this is how we're going to do it right now. When we work on the real project, we will secure the key. So let's go back into our key here. I'm going to just show my key, and this is our test key. We're going to put it right there. That is the URL that we're going to send our request to. And this URL contains all of the request parameters and the APIK has everything we need. Here, let's create the URL instance. Let URL equals URL, and then we are going to use this one here where you can just pass in the URL string. But keep in mind that this creation of this UR instance, it may it may not successfully be able to create this, so we have to check. If you are familiar at all with Swift, if you've taken some courses before, you'll know what optionals are, and creating this returns an optional URL instance, which means it may not be successful. We have to check for that first. One way we can do that is we can say if URL equals URL, right. What this does is it checks. If that is not NL, meaning that it was able to successfully create it, then assign it to this constant, and then we'll move that stuff in there, and then we can use it. But if it is NIL, it's just going to skip and come down here and it's not going to run any of this code. If it's NL, that means it wasn't able to successfully create the URL string, and we can't go on anyways. Now let's create the request. Let request equals URL request, and we're going to pass in this URL instance that we created this one. This is what we created. This checks that isn't NL, and then if it's not NL, if it's not empty, it assigns it to this, and then we are passing that into the creation of our request. Now that we have our request in this constant, we are going to send the request with URL session. This is URL session is what we use for networking. URL session shared. There's a shared session object that we can use. We don't have to create our own. And there is a method called Data four. This is going to fetch the data for a given request. Look it all connects. We can pass in this request now into this method. But take a look. There are two keywords. There is a sync and there's Throws. Those are two different things that we have to deal with and we have to observe. Let's talk about T throws first. This keyword indicates that running this method or executing this task may potentially create an error. It's going to throw an error. That's where that word comes from. And you have to handle the error because you want to respond to it. If something bad happens, you want to take note of what happened, and then if it's something that you can recover from, recover from it. If it's something you cannot recover from, then maybe you display a message to the user and say, sorry, something bad happened or like this happened, we cannot continue. Please try again type of thing. Or you can choose not to handle the error and just ignore it. That's perfectly reasonable for some errors. That is what throws mean. And I'll show you in a sec and how we can handle that. Now, Async is another keyword that indicates that this method is asynchronous. Now, we have to take a little moment. If you haven't done any networking before, let me just quickly describe it to you with this scenario. Asynchronous is something like this. Let's say that You are waiting for a package at home. It's a very, very important package. They're not going to leave it at your door. Let's say it's a new mac book. You bought a new mac book, you're waiting for it to come. And so you're waiting at home, it's going to be sometime today, but you don't know exactly when it's going to get delivered. But you really need to go buy some milk. Right? Or maybe by lunch? Let's say you have to go by lunch, and you have no food at home, you're starving. So what do you do? You can leave and go buy lunch yourself. But there's a chance that that mac book may get delivered, and you're not home. You're going to miss it, and that would be bad. Well, what do you do? Well, it turns out, you have someone at home, could be a mom, could be a dad, could be a brother, could be a sister, could be your spouse. You asked them, Hey, can you go pick up lunch? Because I need to stay home and wait for this book. You send that person to go bring lunch and that person goes and gets lunch while you can stay home and wait for the package. That is exactly what's happening here. Asynchronous means that Just like you're sending someone to go pick up lunch? You are sending a background task or background helper in computer terms, they call it a background thread? You're sending that to go perform this network operation. Go fetch that data from the YouTube API. While I remain here responding to user interaction and just like keeping the lights running, you know, keeping everything operational. And when you get the response from the UTube API, they come back to me and let me know what that data is, and I'll deal with it. Now, why is this important? Like how you had to stay home and wait for that Macbook. If we get the main thread to go and fetch the data and send off the request and wait for the data to come back, then there will be no one to keep the lights running and things operational. It your app won't be able to respond to user interaction or do anything like that. So that's why with these sort network tasks or some data tasks, you want to send a background thread, just like how you sent a helper to go pick up lunch. That's what asynchronous means. Okay. Now that you know what these two keywords means, let's handle the Throws one first because there's a special syntax that you have to write in order to capture the error or potential error that can happen. Let's finish typing this out, and then we're going to deal with these two keywords one at a time. Data four, and we're going to pass in request. Okay. So when something may potentially throw an error like this one, what we do is we have to put it inside a do catch block. So you do something, right? You do the thing that can throw the error in between these brackets right here. So that's what you're going to do, and then you're going to catch any potential errors right below it. And then you can print out any error that may happen. It's going to just put it in there. Now, one more thing you have to do just to indicate that something that you understand that something can throw an error is you put a tri keyword in front of it, right? So you're going to do this. You're going to try this, and then you're going to catch any potential error and you're going to print it out. So that handles the Throws keyword for running this method. Now, let's talk about the async keyword that we talked about. We want to send this task off in the background to grab the data. And come back when it does. What we have to do is put the weight keyword. What this does is it basically says, before we execute any of the code below this line of code, it is going to wait for this to return. Why do we want to do that? Because let's say down here, we are going to print out print out the response. Actually here, we're going to put handle error right here and print out response, we're going to put that right here. Right We wouldn't want to print out the response before this comes back with the data, right? Because then there'd be nothing to print out. By putting the await keyword in front of an asynchronous method, it is going to wait for this to happen in the background. Finish doing its thing, come back, and then we are going to print out the response. What are we going to print out? We have to assign the data that gets returned into something first, just like how we did here, let URL equals that, let request equal that. We're going to say, let data, response, equals that. Now, why did I do this? What is this? This is called a tuple, and it's basically a collection of variables. The reason I did this is because what gets returned is two things. One is the actual data, the JSN data, and the other is the response. There are two different things, and they will get assigned accordingly to data and to response. Now when I print it out, I can print out the data, and I can print out the response. It's not going to run this code until this comes back because of this a weight statement right here. Now I can explain to you what this task keyword is. The task keyword is for running asynchronous methods or asynchronous code, which is what this is. It's just a special construct to be able to run code in the background. You think of it like that. So now we're all set up. After writing all of that code, what we're going to do is run this project. It is going to execute this code as soon as the simulator launches. And then we're going to see some output, whether it caught an error or we actually see the data in the response. So let's take a look at what's happened here. If I open up this console area, and if you don't have this console area, it's actually it might be minimized. You hit that button right there. And you might not have these tabs. So you just just click these buttons in the lower right corner and open these tabs. There are two things to notice here. This This is the data, and we can't see the data. It's just telling us the size of data data. That's what happens when you try to print out data. But we're going to have to parse that JSON or convert that into usable data in our app. We're going to do that a few lessons later. But let's take a look at the response because this can tell us a lot as well. Okay. So if you look for a status code status code 200, that's good. Remember back here in the API Explorer. I think, here it is, okay. CO 200. That means that this is a server code for successful. Server code 200. You can Google it, server codes 200. Means. There are more codes. Let's take a look at what we get here. Now, you can't actually see the JSON data, but you can see some details about the response. But status C 200, that is a good sign. That means that the API accepted our API key. I accepted our request as being valid and it returned response. Let's take a look at what happens if we just Change some of the data. Let's say I mess up my API key. Where's the key? Right here? I'm just going to delete a couple of letters from it and run it again and see what the status code is this time. Is 400. That's 400 is not good. It probably detected the APIKey is not valid. Bad request. Perfect. That's awesome. That's exactly what we expected. Let me undo. The API Key should be valid. Let me just mess up my play list idea a little bit. See how that changes things. It's a four oh four. What's a four oh four, not found. It couldn't find my play list because I messed up the play list ID. So this is really good. That means everything is working as we expected to. But wouldn't it be great if you could actually see the response. Right here, we're just looking at status code of the response. Well, sometimes when you're programming and you're working with networking calls like we are doing now, it'd be super helpful to take a peek into what the actual contents of the response and the requests are. And that's where you use a third party a network debugging tool. So I'm going to show you how to use Proxy Man, which you can use for free with your IOS app development, and then we can take a peek at the actual response and we can see the data. So let's go ahead and download and install Proxy Man. Go ahead and visit proxy maan dot O, and you can download the MAC app. Keep in mind, you can use this for free, and there are paid features, so you can look into that, but I recommend just start for free for now. Okay, so I'm going to launch my Proxy Man. Now, yours might not look like this because they'll probably be onboarding for you. You probably have to walk through a few steps first. But one important thing for you to do is to go down to a certificate and you're going to have to install a few things. So install certificate on this MAC first and then install certificate on IOS and you're going to choose simulators. But it helps if you actually have the simulator up and running. So in your co project, just run your project, so you have the simulator open and take note of what it is, IPhone 15 Pro because it's going to be installed on this simulator. So, Yeah, this is what you do. Okay here. Choose simulators. And then it is going to first of all, this was installing it on your mac. If you haven't done that, you have to click his button. And then it should say found the simulator because you have it launched, so it's looking for it. I should say it's found. And then you are going to choose just prepare simulators. And then it's going to ask you to reboot it. You click this button and it reboots the simulator with the new certificate. This will allow proxy Man to stand in between the requests that your simulator makes and receives, and that's how you're going to be able to see the data, right? So what you're going to do, sometimes you have to restart X code. It's a little finicky. If you don't see what I'm showing you, then try restarting X code as well as the simulators. But if everything is set up correctly, then what you should be able to do is if you run the app now, and you open up this Apps tab, you should see it appear here. There it is. That's my project, right. Let's see here. That's this one. Okay. What I can do is right click and pin and it'll show up up here, and you can see that it sent a request to this domain. It was okay, but I need to resend the request to see the content. Let me run this project again, and you'll see a second request being made, and this time, you can see everything. Take a look at that. This side on the left is request, this side on the right is response. For the request, you can see For the query, you can see all of the parameters you specified, so there's key, there's play list ID, and there's part, and that was all from the URL. But the response is the interesting part. You can see the response code, it's right here, 200. But if you take a look at the body right here. This is the data that was returned in the response. Remember when we ran it in the X code project, this data right here, we printed the data, and it just showed the data size. Well, with Proxmn, we can actually take a peek into what the data is here. Here's all the data. This is a very helpful tool to use when you are working with network calls. Now, if you are having trouble seeing what I'm seeing, I would recommend that you go through the troubleshooting steps. Let's see here. When we chose this, there was some troubleshooting steps you could try and launches some documentation for you to try things out. This is what it looks like. Yeah. Just go through this and try these troubleshooting steps. Okay. Not the end of the world if you can't get this working because as you can see, even without Proxy Man, we're able to send the response or sorry send the request and get the response and the status code 200 and all that. All right. Again, this was a test project. This is not the way we're going to do things like this. We definitely want to secure the key and do things a little more elegantly, not just everything in this content view. So we're going to create a separate component to handle the network stuff, and we'll do all that. All right. But this was a huge success going through this part, and I hope you learned a few things. Alright, now that we know we can connect to the API and retrieve data from it, we're ready to start our actual X code project for the app. In the next lesson, we're going to start a new X code project. We're going to store the API key securely. We're going to start roughing out some of the screens, as well as some of the components that we'll need for the app. All right, I'll see you there. 3. Lesson 03: Creating the Xcode project, views and models: The last lesson, we're able to connect to the YouTube data API and retrieve data from it. In this lesson, we're going to set up our X code project and all of the views and the models. Alright, let's diver it in. First, let's start with a little bit of an overview of how our views will be laid out. I also want to explain how our data model is going to look like, especially as we're going to interact with the YouTube data API. So first off, we're going to start with the home view, and this is going to contain a tab view with additional views. Now, I know in this demo, we only have one tab, but this is set up with the intention that you can add additional tabs. Okay. So the home view will house the tab view itself. And then the tab view will contain instances, one instance of the feed view. And this is that scrollable list of thumbnails that you see. Now let's talk about how the feed view is going to get the data. We're going to create a separate component, let's call that the data service that is going to be responsible for all of the code that interacts with the YouTube data API. And the reason for this is so that we can keep it all in one place, and it'll be easier to maintain and also to troubleshoot and debug. So when the feed view loads, it's going to ask the data service for the list of videos to display. And then the data service itself is going to be sending that network request to the YouTube data API. So in the previous lesson, when we looked at what got return, it was two things, really. There was an overall play list structure, and then within that, there were individual video objects, right? Like dictionaries that contained the video data. So we're going to be parsing that JSON into a single play list instance containing multiple video instances, each one representing the video data. If you don't remember, or you're a little bit confused, don't worry, when we get to that part of sending the network request, getting the data back, and parsing it into JSO, I'll dive into more detail about how each piece or part of the JSN translate to different properties of the video and playlist instance. So once the data comes back, we are going to see a list of data in the feed view. So next, we have to fetch the video thumbnail image data because that image data doesn't get return from the API. Instead, we just get URLs to the video thumbnail. So we are going to use async image to asynchronously. That means in the background, download that image data for display. And we're going to create a separate video row view as a reusable view. And the feed view, which has a list component, is just going to create as many instances of the video row view as it needs for as many videos as there are. And each video row view will have a sync image, which will download the thumbnail. All right, so now we're going to have a feed view that looks pretty good, but we have to let the user tap on a video to view the video itself, right? So that's why we're going to create a video detail view that will slide up as a sheet from the feed view when the user taps on one of those video row views. Inside the video detail view, we're going to show at the top the video player. And then below it, we're going to show the description for the video. And that data will have already. So at a high level, that's how the app is going to look like. There is a lot to learn here. Let's dive in. Alright, let's create our X code project. So I'm going to choose App under IOS, and I'm going to name this YT API app and make sure interfaces Swift I language is Swift. We don't need any storage options. We don't need any tests right now. And I'm going to just create this on my desktop, and source control I did not check on. I'm going to change this to the simulator, so that we can launch it in the simulator and not on my device. Now we can get started. The first thing I want to do, let's bring up the diagram again. We have a couple of distinct things. I like to separate things into folders here. We have our views, which is home view, feed view, video detail view, and Video view, and then we have the data service, which is a separate helper, if you will, and then we have these representing our data. This would be our data model or model. Okay, so let's go ahead and create those folders in our Xcode project. So I'm just going to, one thing that I like to do is to rename this. So, you know, when we name the project, YT API app, that translates to this bundle identifier, Y T API app. But the entry point, they always add app at the end, so one easy way you can do is to right click and refactor, and you can change it all in the same place. You might want to do something like that. Maybe we'll just call it YouTube API app. That renamed it in a bunch of different places. You can press command B to just make sure that it still builds. Let's create the folder now. I'm going to right click. I'm going to say new group, and let's call this Services. Then we are going to create another group called Ves, and then going to create another group called models. Let's Just do that. All right, so I'm just going to stub out all of the files that we need and stubbing out just means creating them perhaps adding some initial code, but we're not even going to do that. Let's just create the files, and then we'll focus on just creating all of the scaffolding. So let's call this is the data service, right? So we'll create that there. And let's just create that initial struct. Then for the views, we're going to say new file, I'm going to choose Swift DI view. First of all, there's the home view. But the home view is essentially like we've got a view here. Why don't we use this one as the home view? I'm going to drag this into the views folder, and I'm just going to rename this again. Refactor, rename, and we're going to call this the home view. I didn't rename this one. Then we also have the feed view. Remember, this one contains the tab view. So we can new file. Swift I view, feed view. Then we're also going to have video view. We're also going to have video detail view. And then the home view. We're going to change this to a tab view. The tab view is going to contain an instance of the feed view. That's the basic structure of our project. Let's just create the two models now. These are going to be swift file because they're not views. So one is video. I going to create the st. And then we are going to create another one for the playlist. Let's bring up the diagram for a second and double check that we have everything. We have the home view, which contains the tab view, contains an instance of the feed view. The detail view is going to be coming up as a sheet in the feed view. We've created the video row view, which is going to be inside of a list component or a list view, in the feed view. We have the data service we created and then the video in the playlist models. We're ready to start implementing some of these things in the next lesson. One thing I would recommend is if you're really trying to learn some of this stuff, it's best to follow along and try this out on your own computer or laptop. Just open X code, start the project, and follow along best you can. You can always download the project if you get stuck. I'll leave the link in the description below to download the project. All right. Now that we have our Xcode project and all of the views and models roughed in, we can start on our data service, and we're going to do that in the next video. I'll see you there. 4. Lesson 04: Sending the API Request: Lesson, we're going to connect to the YouTube data EPI to retrieve data. And guess what? Because we've done this already in a demo project, this should be pretty straightforward. The only difference is that this time, we're going to store the APIK securely. Let's dive right in. First, let's review the end point that we're going to hit with our app. So on the YouTube data API, and I'll link to this document below in case you lost the reference to it. Going to be hitting this endpoint play list items. Essentially, we want to list out all of the videos for a certain play list. Now, this is the URL, and it's going to be a get type of request, and the required parameters, so this is what we must specify. Is going to be one of these. What level of detail do you want for the video items that get returned in the response? And through my testing in building this demo, I've come to the conclusion that snippet is what you need. Now, it doesn't exactly tell you what is included in each of these. Maybe there's additional documentation you can search up somewhere. What you can do is in the previous lesson when we tested out hitting the API. You can just try out all of these parameters and see what you get back and see what you need. Now, what you should be targeting is getting back as little data as possible while still satisfying what you need to do because you never want to return more data because that takes more bandwidth, it takes more time and why would you just do that? Snippet is what we need. It's going to contain the title description, the video image URLs, and that's pretty much all we need to be honest. Now, according to this documentation, this is the only required parameter. However, we still need to specify the play list ID. Otherwise, what videos are we going to get back. We need to tell YouTube, this is the play list that I want to get the videos back for. This is what threw me off in the beginning. I thought I would put the playlist ID in there, but no, you put in there. That is the end point we're going to hit. Now, in terms of the APIKey that we need to pass in, You should have signed up for this back in lesson one. If you haven't, just go back to Lesson one and walk through that process and you can sign up for your own API K. Now we're going to jump into X code and see how we can securely store this API K. First, I want to talk about what storing your API K securely even means because there are so many different ways to do it and there are varying degrees of effectiveness. First, let's talk about not securing the APIK, which is what we did when we were demoing the API. Right in the previous lesson. So we hard coded the APIK directly in the X code project, and that's bad because you may accidentally share your project with someone or put it on source control. So if you're not familiar with source control like GitHub, it is a way for a team to collaborate, multiple people to work on the same code base. So if it gets on source control, especially if it's an open source project or who knows who has access to it? Your key is right there, and anybody can take it and abuse it. So that's what you do not want. Now, one level of sophistication or protection is by putting that API key in an external file. You do not include it directly in the Xcode project, but it sits in a different file, and then you have your Xcode project, read the key from that file. This way, when you put your project onto GitHub, as you can see in this diagram, the key doesn't go along with it. The key stays in that file on your computer, and then you have to manually share that external file with the key to whoever needs access, or that person gets their own API Key and puts it in the config file and combines it with the X code project. Now, the problem with these two methods is that ultimately your X code project still needs the API Key. And the reason for that is because we are making the network calls to the API directly from our project or our app. Our project needs the key in order to access and authenticate against that API. There's no way around this. Your EXCO project needs to know about the key. If you think about the App store, when your app is downloaded, right, that package that is downloaded has everything it needs to work, including the API key, because ultimately your app is going to be using the API key to connect to any APIs which your phone or your app uses. So it's still if someone tries hard enough and they know what they're doing, probably can extract the key out from that package. Ultimately, the most secure way to do this would be to not even make the API calls from your app. You would set up your own API, and your app would make requests to your API, and it's your API that has the APIK, that then makes access to the third party API. In this example, that would be the YouTube API. Then it would get the data back from the YouTube API and then return that data back to the app. It's almost like a middleman, which has access to the key. Then that way, the client, which is your app, will never see the key. Then what you can do is you can have that app have its own user account system that the user needs to sign up for and authenticate himself or herself in order to even hit your API. You can see how far you can take this, it really depends, I think, to me, it depends how many people are using your app. And how critical it is that this API Key never fall into the wrong hands. At the very least, we should put the API Key in an external file and not inside hard coded in the project. This is just a good practice as you're building your app. Now, in terms of setting up your own software and having your app never use the API Key to me, that is a later stage thing. Let's say your app picks up traction, and there's lots of users using it gets on the news, and they You think there may be a risk that someone could target your app, maybe competition or whatever it may be to target your app to try to bring it down because your business has taken off. I think that's a good problem to have, and then you would then think about, how can I make my app more secure and then go through this process of setting up your own API. I wanted to go through all of that so that you can get an understanding of what it means to secure your API Key. In this lesson, I'm going to show you how to put your API Key in an external files. Here are the steps we're going to go through. We're going to create a config file in our X code project and we're going to add the key to it. We're going to set the project to use this config file, and we're going to define a special variable in our P list to reference that API Key. And we're not going to do steps four and five because we're not dealing with source control in this project. But steps four and five, they are the steps you want to do if you are putting this project into source control because the G ignore file lists all the files that should not be put on source control. It should not be uploaded to Git Hub, essentially. Steps four and five, those are things that you definitely want to do if you're putting this project into source control or GitHub, and you're working on team. If you're curious about how those are done, I would just Google how to use a G ignore file, and it's literally just listing your config file like the file name inside that G ignore file, which is essentially just the text file. And you include that G ignore file with your X code project. And then when you push your project onto source control, it's going to read that Git ignore file and take note of all the files which it should exclude, and it will not put those files into source control. Now let's dive into our Xcode project and do steps one, two, and three. Here's our X code project. Let's start by adding that external file. This is going to be a configuration file. Let's right click on this main folder here, new file. At the top right corner, you'll see a filter box type in configuration, just configure. This is the file that we want in configuration settings file. Now, the important thing to note here is that you do not want to include it as part of the target here. You make sure that's unchecked and then create because you don't want to include it. Right? Now, you type in API, underscore key in all caps, and notice this is not a variable or constant. We don't put any swift keywords in front of it. This is more of like a text file. Now equals, and we are going to bring up our API key. There it is. I'm going to copy it, and I'm going to paste it in there and save the file. Next, we are going to configure our X code project to use this configuration file by tapping on the root node here, tapping on project, and under configurations here, you can see there's no configuration set. There are two different types of builds that we can create when we are developing and we're testing in the simulator or on our devices, it's what's called a debug build. A release build is when you create a build specifically to deploy or send to the app store. And that doesn't contain all of the extra stuff that's only used in the development phase of the app, such as the Bug symbols and things like that. Anyways, for both of these, D Bug and release build, we are going to set it to use config like that. Okay. Now, the third and final step before we can test this is to go under targets here. We're going to go into info. This is our P list, and we are going to create a key that we can use to reference that value in the config file. So at the bottom, hit plus, and then you're going to type in and all capitals AP, underscore capital K E y. Press Enter, and the type is going to be string. I don't know why it was a lower case P because I think there was some auto correct funkiness. Let's correct that and change that to capital P. And then as for the value, this is going to be a dynamic variable or reference, and it's going to refer to the API key in the Kfig file. So what we're going to do inside our Swift code right here is we are going to go into this P list and grab the value for this key. And the value for this key is actually pointing to this Kfig file, which we are not going to include as part of the project when it gets put into source control and all that stuff. This is our external file, like we talked about before. Let's test this out. We're going to go into the home view, and we're going to say on a peer. We are just going to print out the API key, see if we can reference it. The way we reference that info dot P list is by saying bundle main info dictionary, that's our info P list. This is optional because it may return NL. If it can find it, then we are going to search for the key. And we are going to try to retrieve the value because it has no idea of what the value is. We know it's a string, it's a type of string, so we're going to try to turn it into a string. And this is just try. If it can't, then it'll probably be empty or nil. We could provide a default value. So yeah, if it can't find anything, let's print can't find it. Okay, for our own debugging. Okay let's try this out. We are going to run this in the simulator, and so it's running right now. And we should see our API key print out there if everything is according to plan. All right. Perfect. It works. This is referencing the info list, looking for this key, and the value for this key is referencing the config file API key right here. Perfect. Now let's move on to implementing the data service, where we're going to send off the API call to the YouTube API and to retrieve the data. So in the data service file at the top, let's declare our key as a private constant. And we're going to call this the API key. And we're going to handle this just like I showed you before, bundle dot main dot info dictionary, and we're going to try to look for API Underscore key as string. Now I'm not going to give it a value like this if it can't retrieve it because I do want it to be NL in that way we can detect if the API K is present or not. Next, we are going to create a new function called G videos, and it is going to return an array of videos. Essentially, I wanted to give back all of the videos for a given playlist. We are going to make this an asynchronous function, and I will explain what that means when it comes time that we call this, and I'll explain what the Async and await keywords mean. For now, why don't we just return and empty video array? Here we're going to implement that API call. First, check if API key is there, and then we are going to create the URL, create the request, and we're going to send the request and then finally parse it. This really helps that we did this inside a demo back in lesson two, right? So we've tested that this works, we know it works. So we're going to say guard API Key not equal NL else return. U We can return an empty video list because it can't get anything. Idally, what you'd want to do is probably show an error message or something so you can return something as such and then capture it and display it to the UI. But by doing what we're doing here, you're returning no videos. So the user doesn't know if there's actually no videos in that play list or if something went wrong. But clearly something went wrong because we can't get the APIK, right? Okay. Coming down here, we're going to create the URL. And before we create the url actually, we're going to create it off of a string, right? And that url string is going to look something like this. First, let's go back to the documentation. So that is right here. And as I mentioned in the previous lesson, we are using this end point right here. We're going to retrieve all of the play list items given a play list. I'm just going to put that right there. I'm going to hard code that URL right here, and we're going to add the parameters. One of the required parameters is this one part I mentioned before in lesson three. Why picked snippet because it contains what we need. Then the other thing we want to specify is which play list do we want to target to retrieve all of the videos for. Okay. So the way you find this is, I'm going to choose my own playlist. You can choose whatever playlist you'd like. But if you go to someone's channel and you go to playlist, you'll see all of the playlists here. I'm going to click on this one, your full playlist. And it's just this ID right here. If you double click it, you'll highlight the whole thing. I'm going to copy that, and I'm going to paste that in there. And the last thing you have to add is the key. So we're going to say key is equal to, and we will just insert that right here, API key. And we've already checked that it's not nail, so we're going to just force and wrap it here. Now we can create the URL instance off of that string, now we can create the request. Let's do that URL request, and we're going to do it off of this one right here. We're going to pass in the URL. Actually, this one returns an optional. This could be NL. We're going to say, if URL equals URL, just to check that it's not NL. We're going to put all of this code in here that only executes if we're successfully able to create a URL instance, then we're going to do that in there. Then sending off the request is a matter of using session. If we say, let's create another constant right here just to make things more clear. URL session shared. This is just breaking things up so it's easier for you to understand. And if If you look at this one, which is what we're going to use, data retrieves the data for a given URL request, which we have created up here, and it is both an asynchronous method and it also potentially throws errors. So we have to address both of those things. The third thing I want you to notice with this method is what it returns to you. It returns a tuple. So it has two pieces of data. It has data, which is the actual data that is returned by the API, and a response object, which you can take a look at for any errors or the status code and things like that. So that is the actual response, and that is the data separated into its own parameter. We're going to also handle that. But first, let's do things one at a time. Let's handle the T throws part, and then we're going to do Async and then we're going to handle the data that gets returned. Throws. Let's pass in the request. If calling a method may throw an error, we have to catch it, and the mechanism in Swift to do that is to it looks like this. You do something that may potentially throw errors, which is this line of code. You have to put a tri keyword in front of it, so we're going to try to do this. Then you have to also have a catch block. This displays, or you can handle any errors that get thrown if it gets thrown. We're just going to print it out. This we'll reference the error that gets thrown out. Next, let's handle the fact that this is an asynchronous method. In order to call the asynchronous method, which means that it gets called in a background thread or a background worker. So imagine yourself tasking someone else to do the work, like you're giving someone else a task and have that person go and do the task and come back to you when it's done. You have to put the await keyword, which means that you are going to wait for that person, that background worker, to come back with the completed task before you continue and execute the rest of the lines of code below it. So that's what's going to happen here. Now, I do want to explain, even though it waits for the background worker to do that task and comes back before we execute the next lines of code, it is still good because while we are waiting for that background task to come back, we can handle any sort of user interaction, and we can also do some other things before we execute the next lines of code. It's just that the await keyword tells the system, do not run lines three and below until that background worker comes back. And for things like this, you do want to send it off as a background task because if you have the main thread, which is the main thread that is executing this code, go and do that work, there will be no worker to handle all of the user interaction and stuff. And so it'll look like it's frozen. So that's kind of the gist of it. With any sort of tasks like network requests or database queries, and you'll see when we do the thumbnail downloading for the images. We're also going to send that as a background worker to go and do that. So that's using the Async and await keywords. The fact that this is in asynchronous method will also come into play when we have the Feed Vew call get video, you're going to see how we use the A weight keyword. Okay. So hopefully, that makes sense, if not, I would recommend that you dive a little deeper into Async and a weight. Search for some additional tutorials on Async and a weight in Swift, so you can understand it in a little more detail more than we have time to cover right now. So we've handled the fact that it throws an error. We've handled the fact that it's an asynchronous method, meaning background worker is going to go execute it. Now we have to handle the data that comes back, and it's a tuple, right? So we are going to declare our own tuple to track that data. We're going to declare a tuple constant. We're going to say data and response. You'll notice that this format looks like what we saw this method returns. We're going to say equals this. So if no errors get thrown, when the background worker comes back, it's going to assign the data to this and it's going to assign the response to this. And then from here, we can parse the data. Now, before we actually parse the data, let's try sending this request off and taking a look at it inside Proximan to make sure that it's happening. So what we're going to do first, we have to actually fire off this request. So inside the feed view, right here, why don't we say on not on a here, but we're going to use task. Let me explain what that is. The task is a modifier that lets you execute a block of asynchronous code. Let me put that into Layman's terms. When the feed view appears, it is going to run this code inside this task block as a background worker. We are going to say we're going to create a property up here to store the videos, and this is going to be a state property. Let me explain what that means as well. It's going to be an empty array in the beginning. In case you haven't watched my eight day beginner series where I explained what state properties are. It's essentially when this value changes, we want the UI to refresh. This starts off as an empty array, there are no videos. But when we send off the task from the data service to retrieve the videos and it comes back, and then it puts the video instances into this array. We want the user interface to refresh and show those videos. That's why this is a state property. Let's fire off this task. We are going to create a new data service instance and I'm just going to chain it like this. I'm going to call get video. That should be an S. We'll change that. This should be get videos and Notice that it's an asynchronous method. And it returns a list of videos. So Asynchronous means we're going to have to send it off as a background task. We're going to have to wait for that to come back before executing the code below it. We're going to say let videos equals that, the return to list of videos. Let's call this. Let's call it returned videos. Then we are going to assign the return videos to our state property here. Self thought videos equals returned videos. We can shorten this definitely, but I wanted to break this up into two lines to explain to you the fact that this line of code will not execute until this has gone and come back with the data because of this await keyword. While the main worker is waiting for the background worker to retrieve the data, it can still handle user interaction and other things that it needs to do. That's what's so great about ACN can await. We can shorten this by just putting this like this and removing the need for this even. All right, but I thought writing it like that would explain the await keyword a little bit better. So with the way we've set it up now, if we run this in the simulator, it it should execute this and then send off the network request. And if our API is correct and our request is structured properly, we should get a response. So let's go ahead and open up Proximan. Let's go ahead and take a look, see this in action. I'm going to first run this in the simulator so that it'll show up on our list. There it is. I'm going to pin this one to the top and I am going to have to resend it. Hello World, send it. All right. The status code is green, it should be a 200, 200, and we get the data back here. You can see the root element contains an array of items. This root element, we represent it with our playlist model. We're going to model it off of that. Then as for the items, these are the individual videos, which we are representing with instances of video. Obviously, we haven't filled it out yet, but that's what we're going to do. If you open one of these videos, you're going to see that it has the snippet, which is what we asked for in the API request, and it contains the thumbnails, the title, the description, and the video ID is also something that we need. So inside resource ID, here's the video ID. So those are all the details we need. And inside thumbnails. You can see that has different sizes of thumbnails. Each size has a different URL. All right, I think we're halfway there. Now with the request being sent out and the data being returned, all we need to do is parse that JSON data into video instances so that we can display it. And we're going to do that in the next lesson. I'll see you there. 5. Lesson 05: Parsing the JSON data into Videos: In this lesson, we're going to turn that JSON data returned by the API into video instances so we can display it in our feed view. Let's dibrt in. The first step is to fill out the properties of our data models according to the response that we get from the Tube data API. Let's take a look again at Pxy Man, and this tool is really helpful, especially because you can just send the request and look at the response and get this tree view and then you can go through it like this. Sometimes the documentation will have the response, so this is the YouTube data API. I know the API Epler if you use this and you try out the request, you're going to be able to see the response. Here, this gives you an idea. Yeah. So if you don't want to use Proxy Man to look at it, you can look at this as well. This would be the playlist object or instance, and this would be the items. Each item is a video. If you click on that, you can see, these are the properties of the video. Actually, let's use this because the text is bigger than we have here in Proxy Man. We're going to start with the video itself. So we're going to add the decodable protocol, and this allows us to turn the JSon data into instances of video using JSon decoder. So let's bring up the API documentation. What I'm looking at right now is a single video. So we can see that it has an ID, which is a string, and this will be helpful for us because we want to put these video instances inside a Swift DUI list and it needs to be able to identify between different videos. So We are going to pick and choose the properties that we want to parse, essentially. So there's going to be string ID. Then there is going to be a snippet and inside is going to be a title. It's going to be a description. Both of these we need, and those are strings. And then there's also going to be thumbnails. Let's first focus on title and description. Again, this is a snippet property, and the snippet itself, you can see these curly brackets, that represents a different instance or struct or object, whatever you want to call it. All of it is representing the same thing. We're going to say snippet is going to be let's give me a type of snippet. I'm going to make this optional in case it doesn't exist. Yeah, Snippet and not snippets. I can make sure that the property is the same, and I'm going to create another struct in here called snippet, and it too is going to be decodable. Inside the snippet is where I would put title and description. O. I mean, all videos should have a title and description, but just in case they don't, you can make them optional. For now, I won't, let's just see what happens. Then inside the snippet, we have thumbnails. What else do we need here? We need the video ID. Let's deal with that before thumbnails because there's quite a bit in here with thumbnails. Let's do resource ID. I'm going to spell it with lower case like this. Let's do that. Then here, I'm going to create another struct called resource ID that is decodable. The resource ID, well, the only one I'm really interested in is video ID, and it's a string. I know that all videos must have a video ID. Let's deal with thumbnails. Was it thumbnails with an S? This was inside the snippet. T thumbnails with an S yeah then this itself is its own thing. We have to define that. Let's call this thumbnails. Let's create another stru called thumbnails, and this is going to be decodable as well. What do I need in here? Let's key. Let's take a look at proximan here to look at a real response. We've got the snippet here, and then we've got then thumbnails right here. Let's open this up. And then there are several different ones, standard medium default high max is. So you can try out these different ones. These are all different file sizes. You probably wouldn't want to get this one like this is the biggest one unless You're showing it on an iPad maybe, or you want it super clear. When I was building my demo, I was pretty happy with medium. So that's what I'm going to go with. Actually, medium is almost the smallest one. Default is pretty small. So this is almost double that size. But I remember why I e medium is because the aspect ratio is different. So you can see that these are about Yeah, the aspect ratio was a little different. Some of these look more square, and some of them look more like a wide screen type of thing. So I figured out after trying them out, that medium was the one that displayed nicely, so that's what I chose. Yeah. So I'm going to say far medium. And what's the type? The type itself is another object. So I'm going to have to create something for that just to how is these three properties. This one is a string. This one is an int, and this one is an int as well. So let's create a strut thumbnail size. This is decodable to what is it URL. Like that height deal. Then this one will be just thumbnail size. Do I have everything I need? I have the thumbnail image, URL, I have the video ID. This is for the video player. Then I have the title and the description. I think this is it. Perfect. Then going back out. This is a single video going back one step. This is the play list. The play list has and items, which is an array of those video instances. If I go to playlist, let's make sure that this is also decodable and we want items. Like that. Let's also, we need to add identifiable, which allows us to use an array of this inside the Swift DUI list, and we have the idea ready for the identifiable protocol, because that's what that requires. And I think we're okay now. Let's try to parse it. Let's go into the data service, and continue parsing the data. We are going to create a JS decoder. C. And then we're going to say decode decode a certain type from. We're going to decode the data from here, and we are going to decode it into an instance of play list. We're passing in the play list as a type, and so we have to add dot self. This is how you specify a type. Oh, I forgot to point out that this decode method can throw errors. It's asking you to do try. A We can put the try right here since it's already in a D block. That's perfect. We don't have to do another one, unless you want to specifically handle that error versus this error. I'm sure you can differentiate in here though when you catch it. Let's capture the result of this decoding. Let play list equals that. Then as you know, our play list instance has items, which are the videos. This is what we are going to try to return. Because remember this method right here returns scenario videos. All right. Let's see how this works. Let us go back to our views and double check what we're doing here. I'm going to set a break point right here by tapping here, which is going to pause the execution. Let's add a little bit more before we run this. That way we can visually see something in the simulator. Let's use a Swift DUI list and we are going to pass in the videos Because the video strut is identifiable, then that is all good. That means we can use it in this list, and then we are going to i for each video. Let's just di the snippet title. If that is NL, just say title. Let me just do that. Let's see if we can see anything come up. Oh, it was so fast. But we could see the rep sorry the request to go out, the response comes back with five items, and sure enough, we see five items right here. Now, I expected to see more because our playlist actually has like eight videos or nine videos in here, ten videos, actually. Let me take a look at here. I think by default, Yeah, the default value for Max results is five. So this is something that you'll want to set as well. Let's change that in our data service. What was that Max results Capital R. I'm going to add that right here. Max results equals 20, let's say. This it's telling us that we never checked the response, so we can just ignore that by adding an underscore. We don't have to name that. A. Let's run it again. Happened so fast there. We have everything. What we did here today by parsing the JSO through looking at the response and then mapping these key value pairs and creating these properties in our data model. This is something that is very common to do. So it's best to get familiar with this process if you want to work with different APIs in the future. All right. Now that we have the video instances showing up in the feed view, the hard part is done, believe it or not. Now, all we have to do is show the thumbnail images in the feed view, and we're going to do that in the next lesson. I'll see you there. 6. Lesson 06: Retrieving Video Thumbnails and Styling: The last lesson, we parse the JSON data returned by the YouTube API into video instances that we're displaying in our feed view. Now, the problem is we don't have any video thumbnails to show, and we're going to fix that in this lesson. Let's do it. Here's what we have so far with our feed view. Let's clean this up a bit. We're going to go into feed view, and the first thing I'm going to do is change the style of the list list style to plane. And then we're also going to remove the scroll indicator. So let's to that scroll indicators. We're going to hide that. And it should already look a little better. Perfect. Then we are going to remove these separators between each item because these are going to be images, thumbnails. In the text here, I'm going to say row separator visibility is hidden. The other thing is, remember how we have a tab view in the home view. Let's add that tab icon right there. In home view, we can remove this on a peer, display our API Key and add a tab item. In here, we are going to put an image, and this is going to be an icon, SF symbols, and we are going to use stack. This one, play square stack. Let's see if I can put it right there. I just did the whole thing for me. Then the text is going to be feed. That already is going to look a lot better. Now let's take a look at displaying those images using our video row view. Instead of displaying a text with the title, we are going to want to create instances of video row view. But we need to pass the video into the video row view. Otherwise, this view won't have anything to work with. Why don't we create a property here that will need to get passed in. And for this purpose, maybe we'll just do that. From, I don't want to create all of that. I'm just going to ax the preview itself. Okay. And let's go back to Feed view, and we are going to pass it in here. See, now it requires that. I'm going to just pass in the video that it's trying to display. Now, in the video row view, let's display the image. Now, remember, we do have the URL to thumbnail image. It is inside video dot snippet thumbnails dot medium do URL. This is a string. We need to essentially hit this URL to download the image data and then display that image data inside a SwiftUI image. Luckily, for us, SwiftUI makes this really easy using a sync image, where you just pass in a URL, and it's going to do that asynchronously. It's going to send a background worker to go to that URL, fetch the image data, come back and then display it inside an image. We're going to use this one because it gives us a reference to the Swift UI image view, which allows us to add some additional modifiers to it if we want to tweak the corners, we want to tweak the aspect ratio, we can do that. Placeholder allows you to specify what to show while that background worker is grabbing the image data. We're going to show a spinner. Obviously, URL is where should it go retrieve that. Now, because all of these are optional, we may not have an image URL, so we have to check for that first. So we're going to say, if let URL equals, and we're going to try to create a URL instance off of that string. If it is able to create this, then we are going to pass this into the Async image call or sorry view as a parameter. That's where we're going to pass that. What is the string again? Well, it is video snippet thumbnails, medium URL. If it doesn't exist, then it doesn't exist. Then we can't show an image. So what do we have to do here to provide optional Default when the optional contains Nil. Be it must be a string. So yes, if any of this part isn't a URL. If it cannot create this string, then we're just going to put an empty string and try to create a URL, and it's going to fail, and it's going to not do any of the stuff in here. Now let's set our Async image. We're going to use this one right here, as I said, and we're going to pass in the URL that was created, and then we are going to double click here. This is the. This is the reference to the image that will get displayed once the data comes back. This is the image that is displayed. This placeholder, we have another handy swift UI view we can use is progress view, which is just going to be a spinner. Regarding this image right here, we definitely want to add a couple of modifiers to it, for example, resizable, so that it can scale up or down, and we want to maintain the aspect ratio. So the one that I like to use, depends on the circumstances. Why don't we just try fill for now? And we'll see what happens. Let's also give it a little bit of a rounded corner. We're going to do clip shape. We're going to say rounded rectangle corner radius is ten. Now let's see if this works. We're going to go back to feed, just double check. It's going to create instances of video review and pass in the video, and then this should download the images. We are not showing the titles here actually. All right? Well, that was pretty easy. You have to admit just like that, we have this. If you wanted to display the titles, you would you can either display it, the titles don't depend on the image, right? So you could put all of this inside a V stack and then put the title underneath, for example. So we could try to do that here. And this would be the title. Video title, and then we can even make it bold. Is it not title? Oh, sorry, snip it title. If it doesn't exist, we'll show empty string. We can line, we can add some padding, for example. Leading, and then you could add just some padding overall or just maybe just to the vertical. Okay. The corners are a little bit too rounded for my liking. So we'll just do five. All right. And that's how easy it is to do that. Alright, our feed view is looking pretty good. All we need to do is allow the user to tap on the thumbnail to watch the video. That's what we're gonna do in the next lesson. I'll see you there. 7. Lesson 07: Video Player and Video Detail View: The last lesson, we finished the feed view. In this lesson, we're going to allow the user to tap on the thumbnail to show up the detail view and to watch the video. Let's dive right in. So we already stubbed out the video detail view. Let's start by triggering this and showing this as a sheet when the user taps on a video. How are we going to do this? So there is a sheet that you can bind to a property. Up here that you can define, which we are going to define as selected video. When the user taps on a video row, we're going to capture that gesture and set that selected video property, which is then going to trigger this sheet, and then content is what you want to show on that sheet. Let's choose that. Let's create this state property up here and call it selected video. This is going to be Nil at first. We're going to bind to the selected video. And as for the content, content. This parameter stores the value of that, which is the selected video. Here we're going to show the video detail view. Okay. Let's capture the tap gesture on this. So on tap gesture, we are going to set the selected video equals V. And let's see if this works. Perfect. Now the next step, let us pass the video details into the sheet. We're going to do that by in the video detail view here. Let's accept a video. Again, I'm going to blow away the preview. Then in the feed view, we are going to now pass in V, which is the selected video. Now let's configure this a little bit. We're going to have a sheet to where the top is the video player and the bottom bit is the title in description. So we're going to need a V stack setup here and let's set the alignment to leading because that makes sense for the text. We're going to have our video player here, which we're going to get to, and we're going to have the title and description here. I want this scrollable in case the content is a lot. Inside the scroll V, I'm going to create another V stack. This one should be alignment left as well. I don't know if I need the first one then. In here, I want to put the title in the description. This is going to have a piece of text, and it's going to be video snippet title. If that doesn't exist, I'll put empty string, and I'm going to want to make this one headline font, and I'll bold it as well. I'll add some padding to the bottom just to give it a little bit of space. Instead of this, I can actually add the spacing here because there's only two elements in here. I'm going to add the spacing of 30 right there. I don't have to put the padding there, and then I'm going to put the description. This is going to be video snippet description instead. Let's see how this looks. I've got the title. I've got the description, but I need to add some padding. I'm going to add the padding to the scroll view. Should I do only horizontal? No, probably I'll add it in all directions. All right. That looks a little better. Oh, scroll indicator. Let's get rid of that too. Scroll indicator hidden. Okay. All right. No scroll indicators. This looks good. Now, I do want to spend a moment and talk about what options we have when it comes to displaying YouTube videos in our app. Now, we could use a web view and display an embedded YouTube video. But they also have a client library for us to use how to embed YouTube videos in IOS applications with the YouTube Helper library. Essentially, they're doing the same thing, but they're making it because they're using an i frame player. They're making it a little easier for you, but this uses objective C. So this is an option as well, which is a little easier than showing your own web view and trying to put the player like the actual web embed code in there. The third option which I explored was to use Tube Player Kit. And this library worked really well with Swift Juan was really easy to use and honestly saved a lot of time. So I didn't even consider the other options, and this is what we're going to be using with this demo. So this library from Sven seems pretty active, as you can see here, last issue was closed two days ago, and the last poll request was merged about a month ago. As with any third party libraries when you use them, you're creating a dependency from your project. To depend on third party code. And the risk is that that third party code becomes out of date, it's not maintained, and it becomes buggy, and then that affects your app. So there is a risk reward consideration here. On one hand, you could roll your own and even depending on this library itself is third party code. I mean rolling your own would be the best thing, but that would take the most effort and take the most time. Versus using a third party library, saves you time of time and you have to gauge whether or not it's worth the risk. In this case, this was really easy to use and it worked beautifully in Swift UI. Seems active, I think the risk is low, so that's why I decided to use this. Let's dive in and integrate this Tube player kit into our project. Let's hit this blue button saying, use this package, and we can use Swift Package Manager to directly import it into our project. Now, you know how in Lesson two, we created a demo project to test out sending network requests and receiving responses from the YouTube data API. This would be a perfect opportunity to do the same. Whenever I'm trying something new, start a new ExCo project, test it out, if it works, put it into your main project. I've done that So I'm not going to go through that again with you and then spend an extra lesson doing that. What I'm going to do is just directly put it into my main project. But in the future, when you're working on your own stuff, I'm just letting you know, you might want to consider not, especially because we're not using source control here. If you are playing around with your code, you're importing things and you mess something up, it's hard to roll back, right? So definitely test things out in a different project first. That said, Let's import this directly into our thing. So go to file Ad package dependencies, and I copied that URL. We're going to just enter it right there, and there it is, UTub player Kit. You can go ahead and hit Ad package. And while that's going on, let's come back here and scroll down and take a look at how we use this thing. So Looking at this code snippet, you import UT player Kit first, and then you create the Tube player view. And it looks like you just pass in the URL just like that. So as an initial test, why don't we just do exactly this? We're going to copy that. We're going to go back here. Let's add package. There it is. In the video detail view, we're going to import you two player kit, and then under video player, we're just going to plop it in right there. And we are going to run this now and see what happens. It's good, it's showing a video, but notice that the frame is larger than the space that we have. It plays. That's great. The controls are there. The video itself it doesn't look wider than the space that we have. It looks like it's fitting the width. However, it does look like there's a lot of black space at the top and the bottom because when you load this up, It takes up so much height. We might have to set the width just set the frame for this so that it fits in the space that we have. Also, we don't want to be displaying this video. Why don't we try inserting our own ID into here dynamically? This would be snip it. But as you can see, there's something wrong here because as I'm trying to do this, it is not working. The autocomplete is not showing up. So we actually cannot do it this way. We can't just insert a wild card into a parameter like this. Why don't we take a look at some other methods that we can use this and perhaps that would work for us? Okay. So this is ultimately what I ended up using right here. So you can configure the YouTube player like this first, where you can actually pass in a dynamic video ID, and then you then you could use that video player view. So let's copy this. Is of, let's configure it here. Then we are going to add our ID there. This would be video set resource ID video ID. If that happens to be Nil, we'll pass an empty string. I don't want it to autoplay, so I'm going to set that to false. Then with this configuration, if you go back to this page, you can see that you can just pass in this configuration into the the YouTube player view. Yeah, so it looks something like this. This is what we did. We configured something, and then we can pass it into the YouTube player view like that. I forgot exactly the snippet of code when I was looking through this. But, if you take the time to read through that, there's a lot more cool stuff that I can do. But I'll just show you how to do it here. When you create the configuration like that, this is Tube player, you can even call it like, Okay. Instead of specifying the URL right here, we can actually pass in the Tube player, the thing that we created up here. I'm going to run it. And this allows us to specify that dynamic ID. There's my video. St the frame isn't working properly, right? But it is displaying the correct video and it is working. Perfect. Now we need to figure out how we can set this frame for this video player so that it fits in the space. You would just go frame and you would set width and height. The problem is that we need to know what that is. Using geometry reader, we can take a look at how much width we have. And we are essentially going to create the geometry reader up here. And we are going to cut the whole V stack, and we're going to paste it inside the geometry reader. Now because this Vtac is inside the geometry reader here, we have access to proxy. The width is going to be proxy dot size width, that gives us the width of the screen. Because geometry reader, the purpose of this is to is to read the size information. So this parameter gives us a reference to the sizes. Now that we have the width, we can make sure that it is the proper width, but we have to set a proper height as well. Only setting the width is not going to work. The question is, what should we set the height to? How do we figure that out? Well, we can express the height as a ratio of the width. We need to figure out for these YouTube videos that get displayed. What is the aspect ratio? One clue that we have is if we go back to, I can open up proxy maan again. But essentially, I want to figure out let's just comment this out for a second. What is that ratio between the width and the height? There are various ways to get this. But let's take a look at this. I'm going to get the clue from the thumbnail sizes. If we take a look at the items and we take a look at the thumbnails, we did the medium one, 320 by 180. If the width is 320, then what is the height? 320/180. The ratio is the width is 1.78, 78 times larger than the height. We would reverse that in order to get the height because we have the width. We would divide 320 by that in order to get 180. Let's see if the math works out. T 20/1 0.7 s78 gives us 180. That's how we're going to get the height. Coming back here, if proxy geometry reader is going to give us the width, then we could calculate the height by taking proxy size width divided by what? Yeah, eight. Let's take a look. So this should work. And sure enough, we have the appropriate width and height. The cool thing was that this would also work like this. Especially if we ignore safe area. That's why you see this part here. If we go back to the home view, we can say, ignore safe area. This might get it to go. There's that padding there, so I don't want to add that padding there. I do want the tab view to be full. Perfect. But now we need to add a padding to the feed view. We'll probably put it in here. Uh, Let's put the padding. Oh, probably just padding horizontal. Okay. Alright, our YouTube player app is looking and feeling great. I hope you learned a lot, and I hope you were able to follow along. Please check out our other courses on the platform. Alright. Thanks for watching, and I'll see you in the next course.