iOS Development Bootcamp with Practical Apps | DevTechie Interactive | Skillshare

iOS Development Bootcamp with Practical Apps

DevTechie Interactive, Learn new everyday

iOS Development Bootcamp with Practical Apps

DevTechie Interactive, Learn new everyday

Play Speed
  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x
27 Lessons (5h 57m)
    • 1. Music Player Intro

      6:06
    • 2. Music Player Setup

      10:54
    • 3. Music Player Models

      6:19
    • 4. Music Player Home View Controller

      7:08
    • 5. Music Player Custom Table View Cell

      20:04
    • 6. Music Player Player Controls

      40:22
    • 7. Music Player Play Functionalities

      14:28
    • 8. Music Player: Player View Controller

      10:38
    • 9. News App Intro

      8:25
    • 10. News App Setup

      10:08
    • 11. News App Model

      6:32
    • 12. News App Network Manager and API

      18:11
    • 13. News App View Models

      9:24
    • 14. News App Header VIew

      13:10
    • 15. News App Shadow Image View

      9:34
    • 16. News App News Cell

      7:39
    • 17. News App Safari View Controller

      14:59
    • 18. Photos App Intro

      8:29
    • 19. Photos App ProjectSetup

      10:05
    • 20. Photos App Models Creation

      13:10
    • 21. Photos App Networking Endpoint

      15:18
    • 22. Photos App Generic Networking Client

      16:55
    • 23. Photos App Concrete Pexels API Client

      7:28
    • 24. Photos App Photos List View Model

      8:34
    • 25. Photos App Photo List View

      24:42
    • 26. Photos App Home View Controller

      22:09
    • 27. Photos App Infinite Loading and Details View Controller

      16:12
  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels
  • Beg/Int level
  • Int/Adv level

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.

9

Students

--

Projects

About This Class

This course is designed to show you as how to build practical iOS apps from start to finish. You will be building many apps. Each app will have its own challenges and we will learn about various different iOS concepts while building these apps.

Meet Your Teacher

Teacher Profile Image

DevTechie Interactive

Learn new everyday

Teacher

Class Ratings

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

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Your creative journey starts here.

  • Unlimited access to every class
  • Supportive online creative community
  • Learn offline with Skillshare’s app

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. Music Player Intro: Hello everyone. I hope you are doing great and welcome to this new video series on building a music player using AV audio kit. So we're gonna be using Amy foundation and Amy kit to build out our own custom music player. And this is basically going to be the music blend that we're gonna be building is playlist based planar. So there are certain or learning objectives that we're going to be achieving basically while building our desk. So let's go ahead and talk about those. We're gonna be learning to build a custom music player using AVAudioPlayer. We're going to be learning how to create a, how to play music from Blair list. We're going to learn how to build a scrubber to basically move fast forward or backward. Like you know, the music or the current song is playing. We're going to learn to build custom Next and Previous. Some buttons to play the song from cleanest. We're gonna learn how to build a custom play important button. And the entire UI is going to be programmatic. So basically in this and storyboarded arrives zip file that you're going to be using. You're gonna be building out the entire UI programmatically. And you're going to also learn how to create a, how to create apps that keep screens from turning off or a dimming. So when the music is playing, your user can still interact with the controls and the music. And when you disperse that, you, then you can resume the normal operation of dimming and basically turning off the screen, just like just like it's supposed to do. Okay? So there are various different concepts that you're going to pick up while building this app. And basically learn those and apply those in different apps or maybe a similar app that he might have created. Okay, so what I've done is I've created a video because I could not stream directly using my phone. So I have recorded a video where we're going to look at the player itself, how it looks, all the functionalities that we're going to explore. And one thing I want to actually mentioned that since x scored 12 and new simulators, there's music playing music is something that has been, that had been there was a bug actually, it doesn't play a music so you can hear the sound and music still blaze, but the output does not come out of your speaker. So I couldn't actually find the solid it's sort of like, you know, solution to resolve that issue. So that's why we are going to be connecting to a device to basically build out while we're building like to see our UI and to see our progress to desktop. God. Okay, so when you see you next time one, when we are building the app, you see me like, you know, my phone connected and everything because we cannot work are for stimulator and just because he can't hear the music being played or an artist, so you can definitely offload the music playing part towards the middle and law that like your music that's playing. Just ensure by connecting the phone, there's different ways. Or he can actually connect, connect your actual phone while building, to build out, basically to connect and test your app when you're, when you're actually building the app out. Okay, I just wanted to mention that like, you know, your simulator might not work in this case. For music Blaine. Okay, all right, so let's take a look at the demo. So personally we have, we're going to be building this player. And there's Against the album songs. And he can more fast-forward. And basically, if you leave your scrubber at the end, the next song is automatically picked up from the playlist. And then it's going to basically play out. And you can click next or previous buttons to basically move forward or backward in the playlist. And you can margin on their playlist. I'll launch another song, another list of songs, so similar functionality next and previous button scrubbers. And one more category. So we have three categories in this case. And we are going to see like, you know, how you can basically also adapt to the dark More than enlight mode. And if you notice, if you, if you notice right here, this view is sort of transparent. So it's actually using the visual blur effect. So this view controller is going to have the blur effect, which is going to reflect on like, you know, let the background view and sort of be visible in your app. So this is something else that we're going to be actually building out to create, to create this, we declare. So you're going to be learning how to actually get this effect in your apps and so on. Okay. So yeah, so this is going to be the app that we're gonna be building throughout this series. So hope you're excited. And let's go ahead and hop right into the Xcode and we're going to start building it out, right. 2. Music Player Setup: Alright, so let's go ahead and get started. So what I've done is I've created a UIKit project. And there's nothing in the project, just, just the empty shell that is created when you create a UIKit project. So that's what we have. So let's go ahead and fix a few things first. So one thing I wanna do is I want to remove the main interface now from Main.storyboard and on delete this storyboard. So we're not going to be using storyboards. So just in leading, this is not going to do like, you know, deleting these two places and I'm going to do we have to actually delete it from info.plist as well. But before we move forward, I want to actually said that the right orientation as well, we're only going to be supporting portrait device orientation. So let's leave it at portrait. And uncheck remaining of these other ones. And we're seeing here and go to Info.plist. Now in input dot P list, you're gonna notice those applications seen manifests. So expand that further seemed configuration. And you keep on expanding. You will see that storyboard name appears right here. So you can actually simply remove this entry. And this is going to ensure that there is no Storyboard That will be used to basically launch our app. Now what we're gonna do next is we are going to go to scene delegate. And as the delegate is where our Steen is initialized. So we are going to basically put our ViewController, our launch point here. So R, view controller, the controller that we want to make as a home controller is launched from here and Esther, OK, like you know, from the storyboard. And now there's no storyboards are programming our app. It's going to crash because it's not going to be able to find mean or in any other entry points. So you need to write down integral. And so let's go ahead and do that. So I'm going to remove that underscore and replace it with Windows scene. And I'm going to be slays window now. So Lindow, UI window and pitiful an initializer that takes a seed. So you're going to say it's going to be window scene and window UI view controller. And basically we're going to be using UI navigation controller. So you are Navigation Controller, Root View Controller. I'm gonna pass her view controller here. And we're gonna say that make this as the key window and make it visible. Okay, so this is the view controller. We should lunch. So I'm going to just give the background to red to make sure that this is the one that we are launching. So when we launch our automobile and taller in the app, you're gonna notice that it's going to have a red red background. Okay, so let's wait for it to get ready. So still, still launching. Right? Okay, then come took, it took a little bit, but here you can draw as is basically lunch. So we are actually now programmatically launching the view controller. That is great. Alright, with that, we are ready. Our project is already basically do build out our Leila functionalities. So yes, the first thing we need to do is we need to import some assets and we need to go in and add some colors and stuff. So what I'm gonna do is because we're actually going to be all sorts of boarding dark moles on the playlist screen rate. So we're gonna do is we're going to create some named colors. Okay, so I'm going to right-click on here. And under acid to start XES. Dan, I'm going to choose a color set and I say decor color. Okay? And I'm going to create another one, which is going to be subtitle color. Ok, and what the okay, so SC bar subtitled entitled color. We're gonna give them a color code. Okay, so for the subtitle, any appearance, so dark appearance you on absolute battle as white or any appearance, read them as say, we need to have a little bit of a darker shade. So I'm going to open the color picker and maybe we'll choose just wondering, okay. Because subnet or died or you're going to make it any abuse to be a little bit darker. So it kind of Blake led in color. Okay. All right. Now let's import some, some assets. So I'm going to import that pre-images for our album colors. Alright, so important now we named these. So I'll name this one jazz. You can pick any image you want. Ourselves belong. Wishing is going to be cinematic. Cinematic. And there's gonna be another one that's going to be a caustic. Alright? So the three album covers that we're going to use now for the music. And all we're gonna do is we're going to use a website called Ben sound data com and Benson.com provide free music so you can actually download music from there. So here's the website that he can use his bends down.com and he can basically get royalty-free music. So what I've done, in this case, I've downloaded the music in included in my project because our main purpose is to build out the music player. The playlist is going to be static, but you can very well use a media that can be dynamically downloaded using S3 or Dropbox or something. So it could be like, you know, another video call. So we can see a call to connect with Dropbox to get your files downloaded so you can actually use them within your project. But in this case, we're going to be actually downloaded. So go ahead and download your songs from here. I actually took three categories. From here, there was acoustics and pneumatic in jazz. So I just basically went into these two categories and they use these Download button, and this is from Ben sounds. So when you download, it actually shows that like free license you have to use with attribution. And there are some restrictions or make sure you actually read those or you can actually get purchased music for 30-40 percent, pay for Euros or something like that? Yeah. Okay. Anyway, so you can purchase the music if you aren't. If you don't want to grind the evolutionary. Ok. So with that, let's go ahead and include our music files. So go ahead and get them music files loaded. Alright, so I'm gonna basically drag and drop the music bias into my project. What's the music files that are included? I'm going to create some worse your folders, so to basically move them into their own corresponding folder. So let's do that. So God, so let me create a new group of query that folder. Maybe this one is jazz. Jazz has all that. Data's comedy. All right, so let me pause the recording and do this categorization and I'll be back in a minute. Alright, so what I've done is basically taken all the music files and categorize them in different categories. Now remember, these folders, virtual or real folders. They don't. Therefore, your organization of your files, whenever your bundle is created for your bundle or bundle, everything is a flat hierarchy. So all the files that are like within your open-door mental level where they can find a lake, you know, all the files. So you don't have to worry about like, you know, having pulled us and stuff like that and finding folders. All you need to do is if you wanna find a file, you just find the file within the bundle. And it's going to basically be able to locate where the filers OK, bundle should be able to do that. Alright, with that said, hey, I've got, I've got three different categories, three different playlists. Then we're going to be increasingly using to play our music. And next, we are going to basically now create our model viles to represent the songs and albums. Okay, so that's going to be the next. 3. Music Player Models: All right, so let's create our model for this. I'm going to create a new group. And we're gonna call this older models, right? And we're going to create too far. So it's going to be one pi. Ok? So for file, you're gonna choose here we're going to call this one song. And import from foundation is fine. You're gonna create a struct gold song, okay? And you're going to create some properties, so we're going to need a name, image, artist. These are all the properties related to the song. And quietly. Okay, so once again, name, image are pissed and filename leads are going to be sombre bodies within their need. Another, another model, and this one is going to be Coal album. And the album is basically going to contain the song. So an album is going to comprise songs. So I'm gonna create a struct name of the album. Image, DO bomb, hence songs. And so it's going to be an array Asanga. Alright. Now what I'm gonna do is I'm gonna create an extension on L1 and kind of create a static function, get that will return and aria album. And this is simply going to return an array of algorithm. So I'm going to create carbon. So let me take the first one and then rest on without basically copy paste. So you don't have to see me typing all these things. So the album name is going to be acoustic. Yeah. The image is going to be acoustic as well. So this is basically your referencing this image right here. Okay? And for the list of the song, so let me create one song. So you've gotta have some with name. And the song that I have downloaded that point is called acoustic who breathe. When he used that. And down this basically, I'm going to use the theme acoustic image, but you can have here an image for your song as well. So you can implement that for the artists. I'm going to basically name it bends sound. Yeah, because that's where I got my my songs from. So I'm just gonna Benson.com as an artist. And urban sounds good. But the finally is going to be the file name in there. Acoustic category, the Christian queries right here. So when I simply copy that and paste it right here, okay? Alright, so this is how you go create your songs and albums that you going to create another song with all the property then step so let me go ahead and basically copy paste the entire thing so you don't have to see me by April, right? Some will actually populate this and go. So these are all the songs that we have. No favorite model. So fluid is something that you can use as a challenge basically. Or what I included to test out if like in our model, needs something like user can favorite their sound. So this can be a good challenge actually, if you, if you're up for it, you can take this and at the end of the project team, extend your music player to allow you the same songs as their favorite or mug that assaults her spirit and stain them somewhere. He could be like, you know, it could be a file or it could be a Core Data database or something that you can use to basically show which sounds are user favorite. Rape. You can create an album called favorite and just play the songs from the favorite. So that can be a really good challenge for you today. Okay. Alright, so we've got all of our album items ready. So discern LBO model. And it's going to have like, you know, all these helper my objects that are different categories. And we're going to basically use these categories to create our day wouldn't be where we are going to be listing out all the playlists and a number of songs inside bad playlist. Ok, so our modal creation is actually ready. So let's, let's go ahead and start building out our ViewController that it's going to basically list out, I'll these models and all these categories, okay? 4. Music Player Home View Controller: Alright, so let's go and go to our ViewController. And we're gonna be building out our home screen. On the first screen, where are we going to list out all the albums that we have? So first thing we're gonna do is I'm going to create a legal album or albums. Open dot get. And now we're going to build out our table view to display this. So let's go ahead and create a lazy var. People view you. Alright, so we're gonna make sure that auto resizing mask into constraint is false. So we can define our own current won't auto-layout guideline. And you're going to make sure that this ViewController X as a data source and delegate for this table view. We're also gonna register a cell, and we're going to call it F1. So let's create register a UITableView cell for now. Okay, and we're gonna come back and create our customer selves. So for the redesign and if I know, I'm going to simply say it's cell. And we are also going to give estimated rawhide. I'm gonna give it directly. And for the rawhide, I'm going to say is he UITableView dark automatic dimension for it to automatically adjust the roadway just automatically based on the content side. For the table footer view, we can simply create an empty view. So extra lines at the bottom of the tableView doesn't show up, the lines that does not have any content and they don't show up. So that's why we are actually going to create for interview and assign it to an empty view. Okay, now let's go ahead and resolve the issue. So I'm gonna create an extension here for view controller. And this is going to extend the UID. We'll, we'll confirm to you I do delicate and your idea will be your data source. Okay? And here, the number of rows in section, we're going to return a one-stop count and parse cell for row at index path, we're going to simply create a cell. And within that dequeue reusable cell with identifier. And enterprise is going to be cell. And it's going to be for the index path that we're going to return a cell. We can simply say self dot text, label dot text. Equal to, but now we can actually just set it do well, bombs, IndexPath, dot curl, dot name. Okay, festive, display something. And alright, so now our errors are gone. So let's go ahead and add some more, Few more things. So first said the title for the page. So basically this title that's gonna show up in the navigation bar. So you're gonna see my music player. And now we can now create a setup function. And are, they will reel, so set up for you. And we're simply going to say that you don't add sub view. And this is going to be the table view. And basically let me put this on there as well. And time to set up. And you're also gonna call setup constrains function, which we have created. So let's go ahead and create that. And these two functions can be private and actually does albums, so it's also private. Okay? Alright, so now we're going to actually set up our constraints. So dv, all right, people constraints. So yes, the NS layout constraints dark activate, people, view dot leading and current constrain is equal to mu dot leading incur were trailing and currently going to constrain it to be u dot trailing anchor. So you're going to basically cover the entire screen with our TableView constraint into your dad, Dao Pinker. Great. All right, with that, let's go ahead and launch. This is see in the simulator. So we're gonna be using simulator until we get to the point where we are actually playing the music. So you can see if the music is being played on R. And as you can see, people view is ready in it's actually displaying three of the categories that we have created their right. And so three of the albums that we have. Next thing, what we do is we are going to create a table view cell. Do display our albums out. Okay, so basically our album tell is L1 cell is going to be a custom cell that we're going to create and we're going to replace that with this new idea will new cells are, cells is looking a little bit like, you know, bearer. Then just a line let me close with Guy. Yeah, just just line entry. So we're going to have like an image and number of songs and they open guide hall. It's all there. Ok, so next up is going to be the new cell. 5. Music Player Custom Table View Cell: All right, so let's go ahead and create a new folder. I'm gonna create a new group for use. And we are going to basically create a new file right here and call this file open table. You sell. Okay? Alright. We're going to import from UI Kit and you're gonna create a final class album. Will you sell? This is going to inherit from UI table view cell. Now reason I actually created from empty file. So you can actually learn in sort of using template. He can learn to basically create your own, your own over edible properties. So you would actually remember more and learn more if you are actually creating everything by hand instead of using the export sport. So that's the theory behind like, you know, not selecting the template. If he, in case you're wondering Quiz Template I'm talking about. So if you go file, new file, so you can choose cocoa touch class and you can actually hear, give. Basically you're pretty example essay, WEB table, cell for example. And you can say your idea, will we sell like that, okay? So you can create these two and you have them, and you can see you have the opportunity to create as a file if you want to create it. But like you know, this is gonna create an empty shell or which is going to have some default functions and stuff like that. But this way you would actually create cleaner. I'm cleaner object because you're gonna cleaner type, because you've got to know like what all you need to implement, okay? So that's the reason any environment you learn more by creating things by hand. So let's create an album property. So album and we are now, but did set observer on this. So whenever this album object is set, we're going to do some operation here. So again, I say your flap album is equal to 0. Okay? Then we have Lake, some things to do here and we're gonna come back to this in a minute. But let's go ahead and create our controls. So we're going to need a, an album color, not color, album cover, a cover. Basically the image to show, album image to show. And then we're going to need album name and song counter. So coverage is going to be UI image view. Oboe name was gonna be UILabel and song God, it's going to be UI level. So the three controls we need there. So let's go ahead and create that. So primate bleeds EUR album cover over. You. We're going to send the content mode scale aspect fill. Your gonna set clips to bound to true. And we also set the corner radius to be 25 in this case and begin to set specific corners. Basically mask specific coordinates. So we're gonna say master gardeners and you want tomorrow. Sorry, layer men, men, y-coordinate or min, min y corner. And later max maximum y. A gardener, sorry, max x and make for a sober. So we can mark layer min x, min y corner. So that's actually, so let's imagine if this was your box, right? So this point right here is going to be your min, min x. And when y right in this corner right here, it's gonna be max x and maximum y. So we just want to mask these two corners. So the Serbian actually saying here, and let me put an equal sign here. So Sarah is gone, and there you go. That's our album cover. And next, we're going to have a woman name. You're going to create a boulder bold font for this album name. And put the text. Color, began to say it's going to be a UI color. And we can then use named Color. And named colors going to be the color around so that we create, in this guy right here, we are going to be using ok. So that's z or bomber name. And then let's create songs count. You've got a set number of lines to 0. So if the L, if more description instead of having songs County and actually have those for the text color, we're going to have once again UI color. So we're going to use the UIColor named subtitle color. I'm going to return the view. Okay? So these are all the controls that we need. Alright, next up, we can now basically create our init. So we're going to use your idea will be you override the initializer, which is, which takes style and reuse identifier. And you're going to basically just lead does as fatal error because we are not going to be initializing from storyboard. So use quarter initializer in your, in East Lansing from storyboards. So we're not going to be using those hosting we're gonna do is reassure down called super data and eta and past the style and sell the user's id. And then we're going to set up our view. And we're going to call set of constraints here. Alright? So for our view and we're going to do is we need to add all these into content view so we can use a simple technique. So we're gonna take our album, cover, an album. Name. Songs count. And you're going to put in a, put all of these in a for each loop. It's gonna basically give us a view. So we can simply say B, S4 view, content, view dot add. So bu, bu vector, just basically going to add all of our views into the content view. Next, we're going to lay out these views. So we're going to set up some constraints. So I won't cover first. Create album cover to have leading anger and go do continental US leading anchor with a constant speed of 16. To this gonna be a gap, a gap of 16 points from leading fight, then you're going to have an album cover, dot, dot. So just kind of stay leading in top. The constraint equal to content view dot top anchor. And this is going to be 16 as well. Now we want our album cover to be specific width and height. So we're gonna say album cover with anchor. Constrain widths do a constant. And I'm gonna say this soon, it's gonna be a 100. But the height, we can say the same equal to class 1000. And you're also going to have a bottom anchor. And constraint is going to be less than or equal to. So you're gonna use less than or equal to constant. So we're gonna say content view, bottom, anchor, less than or equal to negative 16. Now this is basically going to help our view, our table view to lay out the cell and adopted those automatic height. So in this case, this UI dimension, the dimension that we have actually defined, automatic dimension that we have defined right here. Having all the constraints for leading, trailing, width and height bottom is b in basically helps give are orderly out a clue that how big of a cell this is going to be, okay? So this is actually, these bottom properties, bottomed out properties are important. Okay? Next, we can add constraint per album name. So for the leading, we're going to constrain it to the album covers, trailing. So album cover, trading anchor. And then it's going to be some breathing room. So we gonna give 16 points of a gap between those at the top anchor to constrain it to content view, dot, dot banker, constant 16. Well, the trading anchor, we didn't the US content view trailing anchor, negative 16. Okay. Last but not least, songs counter. Alright, so some content's going to be on the next line. So it's trailing is also going to be album covers. Trailing, sorry, is leading is going to be open commerce, trailing anchor, and stop is going to be from the bottom of an album name. So darpa anger, it is going to be constrained to album name. Dot bottom anchor with eight points of gap between them comes through trailing anchor, which is going to be constrained to your content view trading. And we're gonna do the same here. So, so for the songs count, the bottom anchor is going to be constrained to less than equals to constant. So we're gonna see it should be less than equal to content views dot bottom, anchor, negative 16. Alright, so that is our entire album, TableViewCell. Now, let's go ahead and populate there. So whenever our album is that we're going to actually populate all these properties. All these functions and properties are actually created private. So this is the only entry point. So when user this album cell is using this class, the only way it can set basically by setting this album property. Okay, so we're gonna simply say album color. Cover. Image is equal to UI image and get the named image one. Image. Telecom name. Extents kinda be L1. Dogs count that text is going to be interpolated. String, song Theora. So ok. Now once we have the cell created, we're going to go back to our view controller and we're going to say, let's use this instead of using UITableView cell. So let's go ahead and replace this with one table in your cell. Okay? We're gonna keep the, you use identifier. But now if you build, you can actually encounter, well, I'm going to enter encounter narrow yet because our cell is still being cast or dequeued as you add given B cell. So you wanna make sure that in order to get access to the album. So you, you say sell dot. Well, it doesn't exist because right now cell that's been dequeued is your ideal mu cell. Okay? Even though you're saying that there's actually a lewd they will sell because Album table view cell also inherits from UITableViewCell. That means this line of code is perfectly fine and this going to work okay? But in order to get access to the subclass properties, you want to cast this into a cast S1 into a cell called humbled me Album table view cell. And we can put this in Guard LED. And if the cell being dequeued cannot be converted into or cannot be cast into the Album table B cell. Then we're going to say return UITableView cell, an empty cell in that case. Now, this basically gives us the opportunity to access. Now cell type. Cell type, if you look at is Album table view cell. So now we get access to album property, okay? And we can set that. We decorate index path dark girl. Okay. So with that change, we should actually build and run. And there we go. We have our, our acoustic, cinematic and jazz albums listed here with our images and subtitle songs. Now, if you override the dark mode, you can see our music player adapts to that home, right? And your images are, your texts are actually using the color that we have defined for the dark mode. Okay, so that's, that's one of the other thing that I wanted to show. So I'm gonna, I'm gonna lead this lead to solve for now, not operate it. Okay? And there we go. So this is our this is our home view and we have actually finished her home reached an extra hour. We are going to first create a media player. And the media player is basically going to be the AV audio player, which we can use to build out our player layout first. And then are we going to create a music player view controller, which upon selection of an album. And we can launch, so it can actually launch the MediaPlayer and play that media, play that song. Ok, so there's going to be the next stuff. 6. Music Player Player Controls: All right, so let's go ahead and create our music player. So I'm gonna create a new view. And this view is once again, we're going to be selecting circuit file and we're going to call this media player. Okay? And this is going to import UI kit. And it's also going to import the AV kit. It we get basically for any foundation that you use, AV foundation controls AV audio player and stuff like that. Good. You're gonna create a final class Media Player. And this MediaPlayer is gonna have an album of type one, which is can be provided during the initialization phase. So we are going to get rid of this hair in a manner. So this type R D controls first. So I'm going to, we're going to have like, you know, just different things. So we're going to adopt your gonna have our album name, then you're going to have my album cover. Ok, so we're going to call it a warm colors color. So I'm going to leave it at that. You can have like, you know, a sound cover as well. And certainly using album cover. Like, you know, sand governor. And if your song has their own images, then you can display those. Then below album cover, you can have a progress bar. Then you can have previous, play pause, next button. And then you can have, like, you know, your time labeled for elapsed time remaining time, display or song name, artist's names, or all these controls. We can actually create fast. So let's go ahead and create those controls. So private, lazy, Barack Obama. So this media player is always going to be black in the background, is going to be darker in color. So we non cannot adopt to Mordor like Mona. So till now, we are actually having it as darker gray. Text alignment. Okay, next we're gonna create our album cover. So we're going to use the same corner radius stuff. So Gardener radius to be 100, mast bound to be massed. Dark mass by mass. Corners to be topped later, min, max and min lie corner and Claire Max x n max y corner. Alright. Next is the progress bar. So basically this, the progress bar that's going to be a slider is gonna be the scrubber and that we're gonna use to which it's going to show the progress of Sung. And also is going to be a scrubber that scrub to move forward or backward in the song. So we're going to create whenever the value is going to change. That. So what we're going to do is we're gonna create a selector. The selector is going to be called progress scrubs. So let's go ahead and create that function. So mom and dad, and we're going to have to sender as UI slider. So we're going to simply say this is going to be progress scrubbed. And we're going to have changed. And for the minimum tracker, minimum mark, when you own track tint color, we're going to use a named color. So we're gonna say UIColor named SU, subtitle, colorful. This. Okay, and we're gonna create a Previous button to go on the previous song. Okay, so we're gonna be using the SF symbol image names. So images are a vector images from SFM. Well, so for that, we're going to first create a config, right? Your image dot symbol configuration, symbol configuration. Okay, I'm going to give me a point. Psi is so poignant side is going to be 30 or BBS mutton. And then we're going to set the image to begin to send the image. You're gonna get the image using System name. And the image that we're going to use is going to be called backward and dark fail backward dot nd dot bill. Okay? And we're gonna say we are going to get the image with configuration. So this pasty config object that we created and the state is going to be normal state. Ok. We are also going to add to this. And so this class is basically going to act as the target. And from the selector B are going to create. They. Now Objective-C functions. I'm going to copy this guy right here and change some properties. So a sender is going to UI button. And this one is going to be called. David had bad BBS. Okay, that we can use that data. Pap. Previous. Touch Up Inside is going to be the event that's going to be passcode via that. Basically, when you have insight, that's when there's this target action is going to be fired. And we're going to also have the tint color as white. All right? Okay. So then there'll be this. And then we need a Play and Pause button. So this is going to be pretty Western books. I'm gonna copy this and I'm going to create Play Pause button. Okay? And let's see. So it's going to be same. Point size is going to be a 100. It's going to be a little bit bigger than previous and next buttons. And the symbol, and that symbol that we're going to use. Is going to be played our so-called dark veil configuration, going to be best and vivo, Create a member selector progress. Did that. Play? Shows me, is that OK? That play pass that up inside. And that didn't color is going to be quite alright. So initially is going to be the place horrible, but we can toggle between do icons. So you're going to have an icon for a pause in Icon per play, and we're going to be swapping those icons out on the fly when the user taps on the buttons so that logic is gonna go inside. Did, did bab play and pass? So we're going to fill these functions in a minute. Okay? Next up is going to be the next button. So I'm going to once again copy the previous button here. And we're going to simply say in the Next button, and this is going to be a UI button. Same. Inserted backwards is going to be forward. And dark veil. And go ahead and copy this. Yeah. It's right here. Dap mixed. Okay. So points I still going to be 30, okay? And, and the only thing that's going to change this going to be this set image, right? And, and selector and remaining everything is going to be saying OK, because that's our next button. Okay. So we're gonna do is we're going to use a stack view to basically stack the three controls. Play previous splay bars in next button. So let's go ahead and create stack view. So control stack, UI, stack view. Or you're going to use arranged views and we're going to supply our previous button, play pause button next, but this turn our view and we're gonna set the upper resizing mask to be false and gonna set the axis for this to be as horizontal. And we can make distribution. The distribution is going to be equal spacing and spacing between control. So it's going to be 20 points. Okay? So that's our control stack. Now, right below our right below our progress bar, we can also have the elapsed time and remaining time labels. Okay? And so let's go ahead and, and create those two. So though, I think these buttons are going to be below the progress bar, you can have two labels. Elapsed time. They will see UI label in a cryptosystem sides as 144. Wait, we're gonna get them light. Text initiative text is gonna be 0000. Okay. I'm going to run this. We'll now, I'm going to copy this one. And for the remaining time, you can have the same remaining time label is going to be your same. Ok. So that's another label. And below that, those two time levels, you're going to have some name, label. So let me go ahead and paste that. And I'm going to actually say Song label, some name actually, yeah. Well, OK. And there's a label for it, translated out or in dark gray to some size is going to be 16. And you're going to make this one bolt. Alright? We don't need any default text. And return the median pay. Right below the song name, we're going to have artist name, so artist navel and all its one. And it's going to be, the only difference is going to be, is going to have a light weight. Okay? So these are all the controls that we're gonna need for the player. Now. We are going to need the player itself. So we're gonna create a private var player. And this is going to be AV audio player. Av audio player. And can be also going to need a dimer to basically check, check the songs progress so we can update our progress view. So we gonna create dimer. Okay? And we will also need one variable to keep playing. Track index. So which song is being played right now? So I'm going to create. Alright, okay, so with these three created, now let's go ahead and create our initializer. Initializer, it's going to take an album and we're going to assign, so do the album test B now passed during the initialization. We also going to call super dot init with frame 0. And begin to set up, call our setup you Solar Center. You function. So let's go ahead and create a private function u, which is going to call a set of constraints. Okay? Alright, right after setting up our view, what we need is basically, we also need to call our basically cinnabar labeled splay garbled names and album cover images and stuff like that. So let's go ahead and set both inside the before that resolved or Sarah, and when it leave a fatal error and all that, all the code. Now we can say an album name dot text is equal to album name, okay? And cover. Image is equal to UI image named album, Dark image, Excel. Okay? Okay, so all right, y d expect that C. Why is that the system is not system will miss named image, named Jay Z later for some reason are sewing in there. Okay, anyway, so what do we need to do? Right after setting these album information? We need to setup a player. So what we're gonna do is we're gonna create a function called setup player. And they said player is going to set up the player for us. And it is going to also set up like you now, all the information make remaining current progress and stuff like that. So let's go ahead and create our player. And this is where we can actually extract her mp3 files basically from the bundle. Okay? So I'm gonna create a function right here. Set up player. And they said the player takes a song because we're going to be calling this from other places too. And what this is going to do is to say it's going to have a guard statement to construct a URL. And URL is gonna be the URL to our song, which you, you're gonna get from bundle. Url for resource with extension. Suddenly going to say it's going to be song dot. File name extension had be mp3. So all these file extension in between, that's only going to use. If we don't get that, then actually return. Okay? So we're gonna say if the timer is nil, right, then you're gonna set the timer dot scheduled time and you wanna dig the overload that takes, that gives us a target. So we're gonna take this one, we're going to put a timer for 0.0001. And that's going to be self. The selector is going to be a selector that we're going to create. So selector and we gonna create some function is going to come here, user info, it's going to be in L and repeat is going to be true. Okay? So this selector is going to be the update progress. So I'm gonna create a private function, the progress. They say it's going to basically update the progress bar, okay? So I simply say update progress. Actually got to see or to call this in the selectors, update progress Excel. Okay? And basically this is where we're going to monitor the progress of our sum so we can update our progress bar. Alright? So we're going to set that and we're going to also say song name, label, dot text. Said that do song dart him. And artist labeled our text, do song dot artist. Okay. Next, we're going to initialize our player. So we're gonna say Do and AV audio player is basically a player that is initialized for a resource at the URL. So for every song, we're going to actually sort of use the same variable, Player variable and initialize. We initialize it with a new URL that we have extracted point the bundle is now, so we're going to simply say player is equal to try Av. Audio player, contents of URL that we have, extract data right here, okay? And I'll just put a statement here so we have caught the error. And we're going to simply print here dot localized description. Okay? We're gonna set ourself as dialing it formed up layer. So we're going to use that delegate. And I'll show you how in a minute. And we're gonna say, prepare to play. Ok, does actually prepares the audio save, basically lost the file. All the, all the details of amplifier. So it's basically setting up the player, do play the audio. It does not play the audio yet. It actually just uses this to prepare to play. Ok. Just be sure to call this basically because this helps you, helps her AVAudioPlayer determine how long the song is. Embrace different properties about the sung, but the media itself that you are trying to play. We're also going to set AV audio session. And EBRD station has shared instance. So singleton, we should set a category, so we had to static category and category is going to be played back. Now reason is because if you try to, if you don't define this, if and if your phone is on silent, muddier media's not going to play. So playback is going to help you avoid that basically fear for NIH and filing. Even then the music is gonna play. Okay, so it's going to be Playback diaper category. Just ignore this error forum inequity going to come back to this one. Try AV audio session. One more thing for the shared instance, we're going to set active to true. Okay? There's no option that we need to pro tem to click on a remote dose. Alright, and then let's resolve this error. So I'm going to go towards the end of the file and create an extension on this media layer called AV audio Delhi it AudioPlayer delegate. Okay, and here we're gonna create a function. Audio. Did finish playing, dead, finish playing. Now we need this one to play our next. So what we're gonna do is we're going to simply call dip down next. And we're just going to ask next button here. So basically this is a if the user has pressed the Next button, so whenever the song would stop, would finish playing, then this is how it's going to start playing the next song. Okay, so let's go back to our initialization. So our initialization setup you control. And we can. Setup are going to call our setup player with song. So song we're going to use the first song. So benign like you know, be have just initialize our media player. That means the user wants to play because they start playing from the first song. So we can simply state album dot songs. And playing index is going to be at 0th index. So it's going to start from the beginning. Okay? Alright. Next, how basically what we're gonna do is we are, so let's talk about constraints. So our constraints are and to be. So unless setup port album name. Let me do this. So yeah, less than up these constraints. Now, we can do something else, but yeah, let's do this on Customer Name. So yes, settled a leading anchor to the leading of the viewer itself. So leading anchored to the new album name is going to be at the leading of the beause. Leading and trailing is going to be similar, some template and I copy this failing anchor. And the top anchor, an app developer. And I'm going to use some constant here above 16 points. So that's your elbow more color. So trailing anchor and trailing, going to be trailing anchor. And from that top anchor, beginner. Album. Name dot bottom anchor. So album cover is going to be constrained. Album covers stop is going to be constrained to the bottom of elbow name with constant of 32. So kappa 32 points album covers height constraint. You can then give to a constant. And what we're gonna do is we're going to get. From UIs clean and we essay date they're white UAS, main.main dot, dot, dot height. And take the 50% of that. So 50% of the height is going to be the height of album cover. Ok? Next is going to be some name. Leading anchor TO leading, trailing. Trailing is going to be negative 16. The upper anchor is going to be open dot bottom. And it's going to be a gap of 16 points for the song name. Okay, then comes artist label by buildup. So I set up time constraints. But the artist name strain is going to be, so artists there's going to be leading, constant 16. Leading to the view would be Diane copy and paste. Ok, so for the trailing anchor is going to be a trailing negative 16. And that topper incur, it's going to be song names bottom. So right below song name, label, dark inner bottom is better. We can show the artist label and the gap is going to be 8. Okay? Alright. So the SCR, artist label, right below the artists level, we can have our progress bar. So our progress bar, it's going to have leading constrain equals to leading and 16 points. Trailing anchor. It's going to be creating negative 16 and anchor. It's going to be the bottom of artists label, artist, label dot bottom, anchor. To begin a constraint to that move with a gap of eight points. That's going to be our progress. Progress. Oh, our progress bar and then our Elapsed time, remaining time. So we're only going to have leading and trailing, leading in hand doppler. So leaving. And because elapsed time is going to be the label towards the leading fight and remain damn. He's going to be towards the, towards the trailing side of the optimum yield. So this one is going to have top anchor, that constraint equal to constant. And we're gonna say progress bar, bottom, anchor, and 8. Okay? And I'm gonna copy this because the remaining time is going to be similar. Remaining time, remaining time label. Okay? So remaining time label is going to be, so instead of leading is going to have trailing anchor silicon that anchor it from the trailing. So trailing anchor, negative 16 as a constant. And for the top, it's going to be topping her progress bars, bottom anchor with constant as eight. Then it will come our control stack. So, so the stack view that we created for controls for our next previous play and next buttons. You can have constraint that we're gonna constrain. Constraint basically 32 points off gap between the leading and controlling stack self. For the trailing anchor, trailing and negative 32. And for the top anchor constraint to the remaining, remaining time level dot bottom anchor with eight points of gap in between. Ok? So these are our love, our constraints. Now there's one more thing I actually forgot about. The set of view is we need to add these views as the fovea, right? So first thing we're gonna do is we can asset. So Album, label, farm level. All these labels began to send them to white color actually. So I don't actually added like gray color here, but we can actually overwrite it. So instead of using dark gray and white color label. So I'm gonna just remove these guys from here just to avoid any confusion. Ok. So we're going to, as it were going to use that foreach trick once again and again say album name, song, name, label, artist, label, elapsed, time level, and remaining timely walk. So all these labels for each of these labels. And we are simply going to say v dot text color is going to be making just white color. Ok? So that's one thing. The other thing we want to add all these controls to the view, right? So we can now simply say album name, album, cover, song name, artist, label, progress bar. Lapsed time. For meeting time and control. Stack. I'm going to put a four each for these. And these are all going to be UIView types. So, and so few people copy and I'm going to set up our constraint. Okay? All right, so next up, we can actually set up our play pause buttons to handle our logic to basically populate all these things like update, progress, progress curved previous next, play buttons and stuff like that. Okay. 7. Music Player Play Functionalities : All right, so first thing we're gonna do is we are going to create a few more functions. So let's go ahead and go right here. You have set of you. So I'm going to collapse this set of constraints. I'm gonna collapse this one and set a player is also done synchronous clefs that right here. We're going to create some public methods to play and pause, play and stop basically our player, right? So we're gonna create a function called play. Sue's going to let us play or start the player. Okay? And I think we're gonna do is we're going to set the progress bar dot value to be 0. Ok? And you also want to set up the maximum value for the progress bar to the songs lamp, right? So we're gonna say maximum value for the progress bar is going to be a float type. So player against US, duration. This duration is actually better. My end time when prepared to play is called Ok, so you'd actually prepared to play extracts all the information about the media and actually populates the player itself. So we can take advantage of narration, do get their value. And we can set that as the maximum value of our progress bar. Okay? Then we can call our player dark play. And we're also going to call a function which is going to set Play and Pause icon. So I'm gonna create a private function here. Said Play Pause icon. And this said Play Pause icon is going to take a Boolean is plane. Okay? And it's basically simply going to set the, the play pause buttons image. So I'm going to create config. Symbol, can pick, okay. More configuration. We end point size as a 100, Play, Pause button, SIP image. And we can then create a UI image. We can say if this is going to be the system named image, if is playing, right, then you can say it's going to be passed dot oracle, dot fill. Ok. So if the music is playing, show the path cotton. If it's not playing, profess passed, then show play. Pause to honor, stopped. Otherwise, basically just show Play dot, so-called dark veil, okay? For normal state, right? And we also supply the config, so MIT configuration conveying. Okay. Alright. So what we're gonna do is we're going to call this function set Play, Pause button. And you're going to blame we wanna supply player Dart is playing. Since we just started playing with the play. Playing is going to tell us if the player is playing, we don't supply a true or false like you know, here. Because if in case player couldn't play that file, then it would actually sort of making are now play. The player is not going to be in the playing state. So you don't want to assume that it's going to be actually playing something and actually rely on the API that AV audio player provides to set this state. Okay, next we're going to create a stopper function. And this function is simply going to stop the player from playing. We're going to also invalidate our timer. And we're going to set our timer to mail. Ok. So these are basically the helper function that we're going to call from outside when we create this media player ever. Okay. All right, so let's setup our update progress next. So for update progress, we can now simply say progress bar dot value is equal to float of player dot current time. So get the current time of the player. And that is going to be basically the value for a progress bar. Now we also want to set our remaining time label, ylab span label right here. So first let's create a variable remaining time. But we're gonna say a paradox, duration minus player dark, current time. Okay? This is gonna give us remaining time and we're gonna say remaining time labeled text. Now, this damn duration that spin given is, it basically gives us a time interval, okay? And we need to convert this time interval into our format 00 colon DOT road to present like in Armenia minister in seconds and stuff like that, right? So what we're gonna do is we're going to create a helper function right here. So I'm gonna say private, func, get FOR matt date, time. The steak bang. This takes a time interval. So you can say divide that by 60 to get minutes and seconds. It's going to be the time interval or truncate remainder and began to divide that by 60. Okay? And then we're gonna create by implementer number or matter the format dot minimum number, minimum integer. So minimum integer digits we can set a due to paying for my daughter got minimum protection digits to 0. Pay bioinformatic dot rounding mode in pink and set it to down. Okay, so we're down towards 0. And then we're gonna construct string. So we're gonna say guard, let men minutes. String is by employer matter. Formatter, dot string from, and this number value is going to be minutes. Okay? Let me also gonna take second string S a dime. For my Twitter dot string. Ns number value is going to be. Second. We have created returned and dy are 0. So we can return minutes string, colon, colon asthma. Second string like that. Okay? So this is going to be our time formatter. So formatted time we're gonna get, right. So what this outputs basically is it helps us a display that formatted dying for remaining time and the elapsed time to begin to simply say get formatted time for the time interval. So I'm gonna say this is remaining time. And for the elapsed time label, we can say get formatted time with a time interval player dot current time. So if you want to compute this first, he can actually looked like this. Yeah. Alright. Okay, so our upgrade progresses is that now if progress bar is scrubbed to basically user has moved up progress bar. We can simply say a player dot. Current time is equal to C is going to be a floor to 60 forecasting or standard value. So you can assign that to players current time. Okay? And for the previous button, DAP, right? So this is where we can first say player, playing index. So playing index, and we're going to subtract one from the playing index. We're gonna say if the playing index goes below 0, right? So then if it's less than 0, then sent the playing index, playing index, the album, dot songs, dot count minus one. So loop it to the end. So if, if the, if this is the first song and user pressed Previous button, then go to the very last song in the playlist. So this is going to create the loop effect, okay? And then we're going to call our setup player, would play the song. So album Dark songs. Playing index, gonna supply the playing index. And we're gonna also called play. And you can set up our play pars effect, play. Sorry, we said play paths. Player is playing. Okay. So that's going to be our DID DAP, previous function are now did that play in path is going to be simple, is simply checking. If the current player is playing, then we're gonna say player in our pulse. Otherwise, player dot play. And we can call set play, pause. Where is playing here as well. Okay? So that is going to be the Play Pause button functionality. Right? Next is the next point. So if either depth the Next button and exploit button. So we can say playing index plus equal one. If playing index, goals and beyond, greater than or equal to album. Songs start count, right? So if it's more than the sound starts, more than the songs that are present in the album. So we are simply going to say Player Index or playing index to be 0. Okay? So go to the first track and we're gonna call our setup player. And so basically these three lines, we can call them a set of player play, hence Centre Play and Pause. Ok. So this is basically gonna set all of our controls and prepare them to play songs. Okay, so let's see if we have populated all of our functions. So it seems like we have everything. Yeah, the entire media player ready. Okay, cool. So next Apo B are going to create our music player view controller. Okay? Where are we going to setup this media player, okay. 8. Music Player: Player View Controller: Alright, so let's go ahead and create a another view controller so we can simply create a new file. And we're going to choose swift file and B are going to call this one music player, view controller, excel. Okay? Now, MusicPlayer, ViewController is where we can set our ViewController. So even as simply import from UI kit. And we're going to create a find lower class Music. Music player view controller, view controller from inheriting from UIViewController. Okay, and we can now get an album. During the initialization. We, we're going to also create private lazy br, our media player. Media player. And we can supply the album that year. Received set arteries adding constraint to false and return our view. Okay? Now during the initialization, we are going to ask for album. Okay? And I'll say self dot album_id is equal to Album and super dot init with name, name nil bundle as Nell. Ok. Now it's going to prompt us for required. So can I just finish that? Okay. And now we're going to call view did load super dot and you didn't function. Okay. And now beaded load is here. We're gonna setup our Blur view. So we're gonna create a private function, func, blur, add blur view. Okay? And we can, uh, first check UI accessibility to make sure that reduced transparencies enabled. So if it's not enabled, then only we can asset tests, reduced Transparency, produce motion. Do you start doing this and enabled? If this is not true, then only you are going to say self dot view, dot background. It's equal to UI, color dot clear owner. And then we're going to create our blurry effect. Ui. Blur effect with style as dark. And then lawyer here affect view is going to be y, visual effect view. When effect has blur effect and learner effect, view dot frame is equal to self dot mu dot bounds. And learn in fact Bu dot. And we can set the auto resizing mask here. Flakes bowl with Frank smell Hayden flex book away. Okay. And then we're going to simply say view dot, add subview. And matter of fact, for you. Okay? Now, if reduce transparency and the sample is enabled, then becomes simply say moo.com color is equal to UI color, black color. Okay? Alright, we're going to call this and blurred view here. And then we're going to set up call our setup view. Okay? So this is going to be a private function, right? And we can add two v dot, add some for you, and you're going to call media player. Now, one thing we can do actually, instead of calling this here, you're gonna call at blur right here. And I'm going to move this function up. There we go. That's better, you know, setting everything related to view here. And we're going to call set up constraints, set up constraints, constraints right here. Okay? And call create punk, set of constraints. And NS layout constraints. Media player dot leading a credential constraints equal to. So I'm going to save you dot leading. You don't need any constants. Can win a copy and paste three more times. But the trailing, trailing anchor to a banker and bottom peaker. Except now on view did appear. What we're gonna do first is we're gonna call super dark view did appear and he made it. Okay. And we're gonna say media player play, right? So we're going to start playing here. And we are also going to set, so this is what you're going to keep. This is how you're gonna make your view, like stop from dimming your phone. You can simply say UI application. Shared application dot is idle. Permanent stable is equal to true. And mu did. Disappear. You can call us. Do you obtain disappear and emitted? Okay, and then you're first going to stop the media player and UI application. Shared dot is my du. Sable. Do false. Okay? All right, so we've called our set of view, set of constraints. And it looks like everything is, is ready. Now one more thing that we need to do is we need to go into our view controller. And we need to make sure whenever we select a cell, it TableView cell, we launch our music player, right? So we're gonna say did select row at index path. And we're going to get the ViewController music player view controller. And this takes the initializer that takes an album. So we're gonna say albums. Index, bad, dark, road. So getting out one from there and create the music player ViewController. And we're gonna simply say, first, de-select. Now delete D select row at index path and immediate true, and present. Our ViewController. Any major true wind completion nil. Okay, now let's go ahead and launch our, let's go ahead and build first picture everything bills. And we're going to launch our media player. All right, so I told my iPhone to build and then let's go ahead and take a look. Okay, so there we go. A media player, and this is actually running on my phone. So go ahead and tap. And there we go. We have our media player loading and qualifier XP us buttons are working fine. Like I said, because I'm recording, I cannot play the sound at the same time. So this mixture of play and pause buttons. Okay? All right, so now what I'm gonna do is I'm going to record the video on this working in and I'm gonna be right back to show you what I've got in the orbit. Alright, so here we go. We have the recording. So let me play this recording and I'm going to launch. And as you can see, the music is playing, scrubber is working. Next button is working fine as well. And play and pause buttons are working okay. And I'm gonna dismiss large and other category. Play the last song as fast. So Previous button is working fine. So yeah, so as you can see, and our visual effect is also looking okay, so all the things that we did actually I just tested dose on the device and it is it is looking good, so, yeah, so this is it. We have reached to the end of this video series. And hopefully you enjoyed how building out this this media player. And yeah, thanks again for watching and your continued support. Thank you. 9. News App Intro: Hello, I hope you're learning Great. And in today's video, we are going to be building this news app from scratch. And basically four, to build this out, we're going to be leveraging news API. And a news API is basically a free API with, I mean, it's not free exactly, has some pricing, but it's free for a year. So if you look at the praising yourself, it is free for developers. So you can actually try out, develop for like, you know, trialed purposes. And then if you feel awake, you have you have an app that you would like to basically launch into the App Store and you can go out there and buy a business licenses and stuff like that. Yeah, anyways, so we are going to be leveraging this API to get how real-time news articles from the, from various different sources. And basically we get these articles in JSON format. So what are we gonna do is we're going to build this app that is going to render these articles inside the table view. And you're going to basically learn a few things about like, you know, add building while they actually developing this use API. And we're gonna go over the learning objectives of the course in a minute, but let's check out the app itself. So we're going to have this TableView and the header. And basically this TableViews gonna render out these these news articles and ease use article has an image that is associated with that news article. So we're going to display that to say we're going to learn how we can basically better cash our images. And then you also basically, for example, have a, a detail view. And this detail view is basically going to be sf, SF Safari View Controller. As I've surprisingly, controller is basically a way for you to launch our webpages inside your app. And this actually gives you, your user a seamless experience where they are able to launch recently the web website or webpage inside your app. But they still have like enabled to do share watched as on Safari view. So many other apps actually use this view and the benefit is that your app stays within the context. So your, when you, whenever you open this page, your user can always go back to your app. That way you don't lose your user. You'll still be able to provide access to the web via your, your, your app. But user not essentially walk away from there. Will a cookbook. For example, like if he were to build. A in our bed, actually loaned to the URL. And if you were to open actual mobile Safari, then you don't know if you're a user is going to come back on right here. In this case a, you are basically presenting your Heuer, your revenue. Other than that, you're actually giving you the user ability if they want to walk to Safari and basically look at this page or market or wherever they wanted to do with it. But if the simply you want to explore the p's, then they can actually do that and come back to the app. So that's actually the biggest benefit that I see with SF Safari view controller. Okay, so that's what, that's what we're going to be building. So once again, we are going to have this news app built out completely programmatically inside UIKit. Okay, so let's go ahead and take a look at the learning objectives for this, what this app. So learning objectives are. First and foremost, it's going to be that you're going to be building a complete app. And basically it's gonna be completely programmatically so there's no use of storyboards lives. So it's very similar to enterprise level development like you know, where most of the companies don't adapt or don't actually go about using storyboards or M-files due to certain issues that they run into law or like, you know, I in bigger teams. So we're going to be like, you know, creating the entire Arab in basically programmatically. And this actually gives you more. When you create your apps programmatically, it gives you more understanding about the platform itself. So you tend to learn more about like, you know, things that Xcode does for you if you're using storyboards. So that's why I feel like no programmatic way is a good way, a good way to learn about the system itself, right? So that's first and foremost thing and very important. Second thing is gonna be basically MS. Gash. So then this guy is a built-in cached at platform that iOS platform itself provides for caching purposes. And we're gonna see how we can leverage DAC, do cache images, ok. And even if he, how he viewed is basically for this caching and then you'd be able to access the cache to retrieve images while reordering and everything. So it actually works out quite well. Then that you're going to be making a network EPA call to news API. And like I said, we are going to write a network, a simple network manager, which is gonna do basically two things exactly. It's gonna make a call to JSON API for the news EPA. And it's going to make a call to images in cache stores imaging indict, unless gash, we're going to build the layout programmatically. So all the layout sprinklers and everything, auto-layout stuff is going to be problematic. You're gonna learn how to use MVVM within your project. So we're gonna see how MVVM can help basically better, better manage your logic, business logic that you have inside your views. You're going to learn to build reusable views. So we're gonna be creating our fuel views. How, for example, like, you know, there's going to be a day will be so definitely the most essential thing. But other than that, that you're going to have this header view that it's going to be reusable. You're gonna create a component out of it. And you gotta create shadow effect, ImageView. So Aaron Law for, you know, there's certain outbreak or fewer probably encountered this thing. Ui image has an issue with dropping, dropping shadow, so it's not bad, easy to drop shadow. So we're gonna see how we can actually do that. And we're going to build a custom view that'll have an ImageView, its shadow. And so you're going to see like, you know, how a rounded corner in Shadow works out for you. So these are high level learning objectives that we have discussed here, but they're like, you know, a whole bunch of things that you're going to learn. So just follow along and have fun, and we'll build this app from scratch. Yeah, so let's go ahead and get started. And I will see you in next section where we're going to set up your project and started with this app development, okay. 10. News App Setup: Alright, so I went ahead and created an empty project, a UIKit based empty iOS app. And this app is going to basically test literally nothing. I've just created this. And basically we're going to start from here. So if you, if you know a lake, you know, if you've worked with a storyboard or a, you know, that storyboard itself has an entry point marked by this arrow right here. And that entry point actually sort of the system knows that this entry point is suppose to start. So if you go in the scene delegate, you're gonna find that scene delegate as it's not really leverage anything down right here. Basically, everything happens behind the scenes. So to launch it, to even create like Enola, your ViewControllers and entrepreneur controllers programmatically. Or you have to extend a bit more. Dwarfs being given in the c delegate. So we don't do is under scene will connect. We are going to take this underscore out, Im gonna type. We need windows things. So we're going to say window scene to basically programmatically launch our view controller. So we're going to now initialize our windows. Are we gonna say UI window and large UI window with Windows scene. And we can say, this is the window seeing that you have been given to us. And alternatively, what you can do is let me show you the other way as well. So what do you can do is you can say window, UI window. And let's say if you launch it with frame, you can say you icecream dot main dark bands and then initialized. Then you can say art, window, seat is easy calls to window. See better you have extracted out here from the windows, even from the semen, from the current scene that's been given to us. Okay. So that's another way to do it. Alright, so let's continue with the story. And what we can do is we can create our ViewController. Okay? We're going to create an object for that ViewController and we're gonna say window dot. Root view controller is the ViewController object that we just created. And make sure this important, don't wish this important step, window, window. See a window may Key and visible. This is basically you present your view controller. So let's go ahead and give this. You can tolerate your background so you don't background color. And I'm going to give it a read and just kinda launch this to see if we can get this. This red view controller read anew showing up. Okay? Alright, so. This back in. And there we go. We have our readily controllers showing up. That means our view is now being launched programmatically, okay? Now it's up to you. Basically, if you want to delete the storyboard, delete, destroy Warner. Deleting storyboard is gonna take up few things. So you're gonna have to do for your steps. For example. You're going to have to, first of all, go ahead and remove this main interface right here from your Settings. Next thing, he can simply right-click and, and delete the file itself. And that's gonna move that file in. So make sure you actually select move to trash, move to trash can, and move to trash. And then one more thing you have to do is basically go inside your Info.plist and in total enthalpy lest you have applications seen manifest. And if you dig down this scene manifest, you're going to notice that at, at the scene configuration applications Session role item 0, budgets and default configuration, there is a storyboard name enter you right here. So if you remove this entry and save your file, now let's go ahead and end. Give our view controller background color. Maybe this time we're gonna go to right. Now I've gotta notice if it's being loaded on art. So let's go ahead and give it a green. And there should not be any crashes. So they've got like we have our green ViewController and loading up that new sleeker ViewController is being launched programmatically. Now. Now, if you launch without any background color, you're going to notice that it's actually black. So for that reason, one thing that he can do is you can always set the background color to something. So we're going to set the background color, right? It's going to analyze this. And then we go, all right, so we have our ViewController, rainy go. So next thing left, coherent checkout the API itself. So I wanna show you like, you know, what the EPA has. So we can actually go ahead and discuss creating view models in the next section. So okay, so newsy area. So first of all, like, you know, just go do news api.org and get yourself an API key. Ok, once you've got the API key, if you are tempted to copy this, a few for you to do that, but make sure that this is STD BS. So News API for some reason, the website itself has not updated, that it's basically HTTPS is support. It's a board says CDPS, they have not obeyed and the screenshots are T's beaches, but they have support for that. And if you put HTTP and make a SUB Carly Hennessy network transport layer error in your app. And basically not gonna load for that, you have to add a, an application transport there exception. And those not recommended because Apple, Apple discourages any of the network call that is not secure. So they actually, they might reject your app submission on the basis of like, you know, on the basis of this fact that you are actually trying to make an unsecure network or so. Just make sure all your network cough are on HTTPS and hear news API does support that. So just changed copy this URL and chooses to ace two dB s, Okay? It's sort of a face UDP and you should be fine. Okay, next thing. So neither API actually gives you a whole bunch of categories. So we are going to be looking at this top headlines. And we care. We're going to be actually working on dub, dub headlines for country us. So I literally just selected these, this part right here. But he can actually choose other categories. And I would actually encourage you to build, to extend this app. Further, do provide the ability to select different categories, okay, so that can be something that they got the challenge after you're finished with this. Okay. So yeah. So these are like, you know, a few things I wanted to mention. Next thing we're gonna do is once you get the API key, go ahead and create a folder called config. At the news api. Like for example, I'm going to create that folder right here. I'm going to call this config, okay? Yeah, and we're going to create a new file here. And we're going to call this file API key. Okay? And what this file is going to convenience basically, the API key that even a get from the music PI website itself. So I'm going to create a strap here, API key. And this is going to have a static variable called key. And this is where I'm gonna based Mikey, okay. This way, you get to keep your keys separate and when you know like yours checking in these projects into GitHub repo or something, then you can simply removed these keys from your code and security checking into public GitHub or public domains and stuff like that. So your key is not compromised. Ok? Alright, so go ahead and do that step. And then we're going to start working on our news model, okay. 11. News App Model: Alright, so once you have basically your API key setup, now it's time to work on our, on our news model itself. Okay? So what we'll do is we're going to construct a model. I am going to be leveraging JSON decoding or with decodable, decodable protocol to, to basically decode these JSON response for us. So we are going to be creating. So if you notice the JSON response itself comes inside an envelope. And basically, the response itself is a dictionary that contains status, total results, and an array of articles in beer is initially interested in this array of particles. So what we're gonna do is we're gonna create an object to basically a decodable object for this news envelope. Pest can help the Hatti-land news articles. And then we're gonna have a news object itself, which is going to have these keys right here, which are going to be decodable. So we can easily decode, or basically we can lead, lead to Swift simple system. Our iOS basically decode these for us just by conforming to decodable. Okay? Alright, so I'm gonna do is, I'm gonna create another folder right here. It's going to be a new group. And we're gonna call this on models. Okay? And we're gonna, I'm gonna press command to add a new file. And I'm going to add a new file called news. Okay? And we're going to create two strokes. So I'm gonna just create two strokes right here. But if you want to create separate file, that's actually don't be violent. So I'm gonna create a struct. Call US. Okay? And it's going to be conforming to decodable protocol. Now this news is basically going to have these keys, the keys that we are now the information that we want to extract using decodable. So we need an author, title, description, URL to image and you yourself. Now neural two immediate basically going to be used to download the image and the URL itself. You're gonna use to basically launch a theft of our view controller to display that article on a web view. Okay, so we're going to create three properties. Okay, so if you notice all of our, all of our keys that we need are of String type. And so we are creating string. And Renan were actually adding optionals for these because any of these could be, could be now. So any of this information can be missing. And our happens basically your decodable. If you don't provide an optional property, then it thinks that it's something that has to be there. So your, there is a possibility for your triggered fail in your app to crash. So for that reason, just for safety purposes, because we are using third-party API, we know that anything could be nil. So in that case, we're going to mark all of these properties as, as optional hand. We should just be fine that that, okay. Now, let's create this unwarranted I was talking about now, which contains the articles. So we can simply create the restrict hear, news angle up. And we're going to have some property. So we have status with your doc type string. We have total results of type int. And we have another property called articles right here, which contains our news articles. So we're going to have that. So particles is going to be an array of news. Okay, now these keys have to be there. They have to be exactly same as what we have here. There is a way where like, you know, if you want to make your keys different, you can use cooling keys. So go ahead and restart your bit about decodable or quotable protocol with cooling keys. And you're going to find out, which essentially lets you change the names of these keys. But for, for simple cases or firm, for a lot of homework, you know, you can keep it same and decodable actually works. Works just fine for the decoding purposes. Okay? All right, so let's go ahead and check out our model one more time mixture, everything that we need, we have it here, so we have our title and description. Invest your URL. And articles is a news array with total result as in type. Status is string and total results. So let's check is int type. Yes. Okay, cool. Alright, so that is all the other things that we're going to need for the, for the model itself. So let's go ahead and check out the network managers. So we're gonna create Network Manager Next and going to make some API calls. 12. News App Network Manager and API: Alright, so let's go ahead and create our networking layer. So what we're gonna do is we're going to create a new folder in new group. And we're going to call this May 1 be services. Inside this folder, we're going to create any file. So command. And you're going to create a file called network manager. And the manager is going to be a class. Alright? Okay, so there are few things that we're going to need. First of all, we're going to be using NF cash for caching our images. Okay, so let's go ahead and create a, an image carried away but alcohol image gash. And we're going to use NS gash or this. And ns caches are generic type that takes types for the key and the value. So we're gonna say NS string is the key and NSData if the value that we can now hold inside. Now, we will create this network manager as a singleton. So we're going to initialize it using a shared instance and we're going to create static let shared Network Manager. And better we're going to initialize it now in our, in our upper us to prevent from anyone else or any other classes do initialize sets. We're gonna create a private initializer. And Barry's going to basically restrict the initialization for this micromanager. Now, we are also going to need a couple of private property. So we can need a base URL. So it gives us a primate lead base. You are L string. And this is going to be the base URL for the news API. So in our case, the base URL is going to be this until we too, because everything else is a query. So if you noticed news api.org slash B do is common between all the other types of API of news article categories, right? So this is gonna work as our, as our base URL. Okay? So we're going to take that and make sure to replace HTTP, HTTPS complete. We're going to need another one. And I'm gonna use us doll pen line. In your case. If you want to change this, you can actually change this to have a, an enum that can be selected using a segmented control at the top. And then you can choose different categories, okay? So we're going to choose. Dark headline, country US. Okay, so I'm gonna copy that. And that is going to be our category or subcategory basically, other than the baseball analysts and we are category for the new API call. Okay, next we're gonna create a function, get the news. This is going to take a completion handler of escaping type. And it is going to return a closure. News array. Optional. So News array can be empty. And so again, obesity return nil. If we've encountered an error or something, then we can return nil here. Now, alternatively, you can use our result and a resulting gas or have another video. I'm using this just to create irradiation to show you like, you know, if you want to pass concrete objects, basically you can do that too. And the technique how you can actually pass the concrete object. But if you wanna see how you can use Result object, in that case is check out the other tutorial about building Photos app in that actually shows you a generic way of making a network calls. Okay? All right, so here we're going to first get the URL string. And we're going to construct the URL string by string interpolation. And we gonna say, will base your string without any space. Began to add us darpa headline. And then we're also going to need the API key. So I'm going to say API key is equally. Okay. Yeah, this is where we're gonna use our API key file and say api key dot key. Okay? So if you go back, you're going to notice is this how we actually bass API key as a very string. So I'm going to go back and paste it and make sure it's typed correctly. Remove one equal. Okay, there we go. Alright, so this is our URL string. Now we're gonna put a guard statement. And if we can extract the URL, this URL string, then we're going to continue. Otherwise we're gonna return from here. So I say guard. Let URL is equal to u r, l constructed from string, URL, string. Now. So I'm going to click keep talking about like, you know, the improvements dizzy can make or challenges that you can take as a part of group. Like, you know, this app building. So you can improve upon things. Basically one of the other thing that he can do is you can have this getting us past the URL string instead of constructing it here. So, so break now we are constructing a URL string here. But he can actually ask the user, depending upon the category that they have chosen, your function picks up a different URL string and that's being passed in, then you actually try to extract it out. If extraction or our URL object creation is successful, then you continue. Otherwise you return from here. Ok. Next we're gonna create a URL session, shared session dot data to ask, are we going to take the overloaded method that actually takes a URL and has a completion block. So you're gonna take this one is actually create a task to retrieve content from the URL. And it has a completion handler that gives us data response in error. So we're going to actually use that one. So we already have a URL, so you're going to pass that URL to hear. And for the completion block, we simply going to hit enter and we're gonna get Leader response in air. Okay? So we're gonna check if the error is nil and air is nil. And we can extract data. So data is equal to data. It, we can't do any of those. Then what we're gonna say is completion is nil and we're gonna return per year. So this is our indication in this case that we don't have any results. And what you can do is there's not going to be n desk or we call. Okay? So what this tells us basically, what this tells us ASB is basically we have an error or a data is not present, and that means the completion block is going to return. That means no news article has been bound. Now, you can further extend this by capturing the specific error and then display that error. Or capture better and have a backup. Basically a backup call to retune news from another source. Okay. That's a topic for another day. So I'm going to just continue moving forward in this case and we are going to extract the news on up. We're gonna use JSON decoder. And we're going to go down a new angle up from data. And then we're gonna say if news on envelope is nil, in that case, we can now say completion is going to be called when they're nil. Otherwise, completion is going to be called Witness News onlooker dot articles. Okay. This guy. Builders and see what's going on. News envoy up to me, decodable. Okay, so I guess I forgot to mark this decodable when k We can go back and we should have articles, okay, so we, since we are already checking for news articles and news unwilling to be nil, we can actually force unwrap or you can, you can simply put a guard statement here. And you can return either part of current guard stable for the nil or completion handler with articles. Okay? Now, the most important thing is and call resume. So our network goal is successful, basically is made and data has been downloaded it because if you don't call resume than this task is just gonna sit here. Go do nothing, okay? Okay, so it's time to test our network manager. So let's go ahead and we'll go into a ViewController and we're gonna say network manager, dot shared, dot, get news with completion. And you're gonna get news article here. So you're going to say, if let guard led needles as equal to news. Else, return. If we found some news then began and simply take the article and print its title. Just as a test to basically see if we are able to extract the news article out. There. You can see we have a news article that we can extract out. So that means our coil is working fine. Put it. So let's go ahead and remove this, right? And we need one more function here inside this network manager. And that is going to be getting the image. So we can guess that image from the URL so we can create a function. We get image for the URL string, string, where the completion, which is according to have completion block with data. And you're going to put a guard on the URL. For the URL string. We can simply return nil completion and return from here. Now, if, if we can get the gashed image, so we can say if let gashed her image so we can just check our image cache first. Image cache data object for key. And we can take our URL string and then construct the Out. So steaks string, URL, string. Okay, so we're going to basically do a lookup based on the URL itself, URL string itself, and see if the image already exist in the cache. So if it does, we're gonna call the completion right here with gashed image as data, because that's why we are actually storing this data and you're going to see what we're restoring now. So if we don't find a cache image, we're gonna make a call to URL session for the shared session with datapath. And then we're going to use our URL that we've constructed right here. And you go take, we'll get data response error, right? You're gonna do the same check Guard. Air is nil and data is present. Otherwise, we are simply going to call nil completion and return from here. Otherwise we're going to say self dot image gash dot set object. So we're going to set the object for KI, Okay? So the object cell is going to be data and we're going to pass this as NSData. Because ns gash or takes NSData and NSString to cast that as NSData. And for the key, we're going to actually use NSString string overload. And we're gonna pass the URL string. So that is basically storing our image in the, in the cache. And we can return data as a completion block. Now, forget to call resume. And let's check out what we are doing here in bart. Okay? So first time when we get a request to download an image, what we're gonna do is we're gonna check, we're going to check our image cache and say, do we have an object with this key? And the key is basically the URL string, okay? And this architect actually gives you data. So if we have stored, so for the first time, it's not going to find anything here. So it's gonna go into this else block and URL session is going to be called and it's going to make the network requests. And when it comes back, it's going to set the image gash object and store data for key, that is your a string. Okay? So that URL string key, just like a dictionary, use beta being I can dictionary, so it's going to store that URL string as the key and data as the value and call the completion analysts will be actually provided the collar data back. But at the same time, we also store that data inside our cash. So next time when the same URL is being called for the same URL image. Then we check the gash and say, Hey, do we have this? And if we do, then return that from the cache instead of making inaccurate goal. So that actually saves us a network, call, it a for 16a awake SU 11 member call for a one request, right? So if you have like in a user scrolling up and down, lay comatose dimes, you have your images cash, you don't have to make network calls or lower because your image Gas, Gas is going to keep the track of all the images of them is going to cache all the images for you. Alright, so that was our network manager. Okay? So with that, our network managers complete, so less coherent checkout. Basically the view model creation first. So we're going to create our lists, we model it and we can see what a warden thinks we need in ListView model. And then we're going to start constructing our views around the, there will be a solid, okay? 13. News App View Models: Alright, so now we're going to basically create our view marbles. So we're going to need to view models we can use. There's gotta be a ListView Arnold that's going to be used for presenting the list. Now, for each individual cell, there is going to be a dual view cell. In that table view cell is going to have its own model for news articles themselves. So we can actually extract all the data out and integer of sending optionals, we can ascend the actual value. So let's go ahead and see how we can actually wrap those things around inside a ViewModel. So I'm gonna create a folder called b. And you're going to add a new file here. And we're going to call this file News ViewModel. And new theme is going to be a struct, which is gonna have, it's gonna be called New few articles. And it's gonna take in news, right? And it can have some properties. So for Arthur, So this is basically going to be a sort of like a rapper. And for, for our case, I'm simply going to say if New start Arthur is present, then send that otherwise, Sander unknown. Alright. So this just to give you an example that you can have a nother wrapper object which can basically sort of massage your data are like, you know, give a different presentation if you want to include, for example, if the image is missing and you want to handle that nil case rather than handling that nil case. If the image is nil, replaced it with something else and stuff like that. So you can do all these things in this wrapper object. That's why we are creating. So we can recreate one for title. If there's nothing, then we simply return the empty string. Same for description. All right, so it's basically going to be the one that I was talking about. If the image, if the News dot URL to image is nil, we want some sort of filler, we want some sort of image to show here. So what I'm gonna do is we're going to use just, I just Google like you know, a simple an image from kind PNG.com is just a transparent breaking news. Png sort of related to the news news app. And I'm gonna display bad instead. Okay, so if the, if the URL is nil from the API, then we're going to display this image, download it from this URL so you can actually replace it with any other image, your app logo, or anything of that nature. Okay, now, that's our news ViewModel. Okay, now let's go ahead and create a list view model, news ListView model. So I'm going to call this new list view model. And this one is going to be basically used by our ViewController to basically get the news article. So I'm gonna create a class list, one and we'll use the model. You're going to use our new view model that we have created earlier. Do basically this is how I was telling you like, you know, we can use the wrapper because we know that when we get the news ViewModel, all the, all the articles that you're going to have received are going to be non optional basically. So you don't have to like, you know, put that if it's present, then do this and stuff like that. You have much more cleaner way of handling your data that you have inside the object. Okay? It is also going to have a reuse ID that we're going to basically use as a salary you ladies, so do use IT IS news. Now, lists we model can have anything that you can think of. That view model can provide which can be reused or less. Imagine like, you know, you had another ViewController. So right now you have a weak control and they're showing they will. But you want to provide your user ability to change that they will be undo collection view and show a grid layout, right? So what you can do is you can still have all your UI logic built with a different ViewController and upon the buttons click a different view controller view, whichever it is. But on a button click, you can change the layout. What you review, my law stays the thing so you don't have to repeat like that code. So that's actually the purpose that, that is that you are actually solving. The purpose for this ListView RLS basically provide that data source that does not change despite the layout images. Okay? So we're gonna create a function, get news, and this is going to have a completion block of escaping. This is going to return void. This completion block is going to return a new view model. Okay, so the longer our returning news, we are actually returning news ViewModel. And here we're going to call our network manager. Share an instance. You get news, ok. And when we get the news, we get the new array back, not the news ViewModel. And what we're gonna do is you're going to say guard, let news as equal to news to make sure that we have something. Otherwise we're gonna return, right? But we do get something. Then we can say, let news, WE M newsreel model and we're going to map the news. So we're going to simply say map, okay? And I'm not going to take, so I'm gonna take this initializer, but I'm not going to build it like that. So I'm going to simply say News, view model dark in it. Okay? And since this init is taking in news, we don't have to like put that news and they're just simply calling init is going to be fine. So it's basically going to take that first object, the new object, and put it into the newsroom model for the initializer and get the ViewModel back. Okay. And then we're going to call dispatch queue dark, Maine. Do you think now here we are actually moving ourself into the main thread because Network Manager is called on the background thread. So we're going to move ourselves into main thread before we update the UI. What's going to happen is basically this function called get news is gonna be called from the viewController, which is going to read out the deal with you. So we don't have to worry about basically changing the trail style so you can grab that piece of code inside your view model itself. Okay? So we're going to say self dot vm is equal to news. We okay? Completion news. All right, so with that, our our view models are basically complete. Next up, we need to create our table view cell. Do display each individual news item and our header view and our shadow image view. So all these three views that we're going to create first so we can compose them inside our ViewController and ate the immobile. Ok, so next up is going to be creating, we're going to, we're going to create our obvious for us, okay. 14. News App Header VIew: All right, so let's go ahead and create our header view. So we'll create a new folder or new group here called Views. And inside this view, we can create a new file. And I'm gonna call this one header view. And we are going to import from a UI kit and going to class called header view. Because going to inherit from UIView. Okay. Now the standard view is gonna take, it's gonna have some property, some UI elements and stuff like that. So let's start laying them out. Busting gonna need as a font size. And then we're gonna create our heading level. So these are, and we can make this a final class because we know we're not gonna fund the inherit from this one. And the text for this one is going to be a heading font. Do the font size. Then we can have a circle image, which is going to be a large circle. So let me see if I can. So I think this is the, let me launch the other happen. Alright? So this, this circle right here, this is what we're going to draw and we basically get this from ff symbol. So you have as FOMO app, open it and you're gonna see this image is called large circle filled circles. So we're gonna see how we can actually use as a symbol will be a UI image. So let's go ahead and create a private Gliese who are adding circle image, UI image view. And we're gonna create our image view. Let's return this. Let's make sure it's Translate. Ro sizing, auto, resizing mask into constraint as calls. So we provide the auto-layout constraints not assisted content mode. Let's set this content more to scale aspect effect. Okay? Then we're gonna create a config. And this config is basically going to be UIImage, dark symbol config, or simple configuration. And this is where we're going to define or give the point size. So we're gonna say we need point size and weight. So point size is going to be the font size that we have. And the weight, basically bold and light and stuff like that. So we can say it's going to be bored for the weight. Okay? And then we can simply create the image are set v dot image, do UIImage with system name, with configuration. So we're going to use the old or that takes the configuration. And we can say the image name itself is that SF symbol. So if you select the symbol and press command, shift C, you can actually copy the name of the symbol or name of the image, right? And then the configuration is basically the config object that we created right there. Okay? So that's how you, that's how you're going to basically create your image. So let me actually resolve this error by creating this create our own initializer that takes font size as the new sludge Asian property of type CTD float. And we're going to set this to have dark font size is equal to 400 size. Okay? Then we're gonna call super dot init with frame 0. Okay? And we're going to center translate is equal to false here. Call setup view, which is going to call setup constrains function. Okay? Alright. And we need an acquired initializers, so we're gonna leave it add fatal error because we're not going to be initializing this using storyboard because as needed, if you are initialized in your view, we storyboard, okay. Alright, so we have heterocercal image. Now. We need that plus icon next to the image. So we're gonna create a private lazy var. And once again, we're going to create our configuration here and you have the image. And this time we are simply going to use x o. And now there's one more thing that we need to set is we need to set the rendering mode or these. So we're gonna say rendering mode for the image is going to be always original. So same thing goes for during world. Always operational. Ok. All right, so next we're going to create our stack view, which is going to have this so-called image heading level and plus emit all these inside a horizontal stack me. Okay? So can I create that? And since we already have like, you know, all these reuse, we're going to start calling them. So going to say heading, poster, header, image, then heading, label, then plus image. In that order. Set the access for the stack. We'll do horizontal. We cannot return them you pay. Now we also are going to need this headline, this sub-headline, right? So we're gonna create a new file that for backer. The bigger set, the font size that we have been given. And now this is something that you can primary diets of law. I'm actually just going to accord it here. So a top headlines. And you're going to set the text color to be gray. Ok. So now we are ready to basically set the set of w. So we're gonna go ahead and go inside set of BU. And before set of constraint call, you want to add subview, pasta file header stack view. Now this makes it easy basically for us to add all the sub views inside the stack view. And now we can add directly the stack view, right? And we're going to constrain stack mu and all the other constraints, all the other views are gonna be constraints, constrained or setup inside the stack itself. So add stack view, sub-headline is actually outside. So some airline label, it's gonna go as the sibling For the stack view and then set of constraints. So it's going to be called her and we're going to be setting up the constraints. So first, let's set up news header and ESL ER. And there's layout constraints. Start, activate, takes an array of anchors. So we can say header stack view, leading is going to be constrained to leaving anchor. Anchor is going to be constrained to put darpa. Alright. Next, we can set the sub headline constraints so you can actually have all your constraints in a single actuator array are a separate choices. You want to say. There's no performance impact between the pseudo header is going to be constrained to the bottom anchor of the header stack view. So we can assembly saying hello stat, dark, bottom anchor and space out by a point. And then going to say sub headline label dot bottom anchor, constraint. Constraint to bottom anchor. So okay. Alright, so that was our next up. How are we gonna create our shadow image and then construct our cell. 15. News App Shadow Image View: All right, so let's set up our interview now. So we're going to create another file. And this file is going to be called shadow ImageView. Okay? And we're going to be importing from your I get class shadow image view, let's say inherit from UI, UIView. Okay? And we're going to create an image here. And this is basically going to be the image that the user can set. User are best shadow imagery you can set. And whenever they said, we're going to call dataset observer. And then we can say Image, View dot image is equal to the image. Now imagery doesn't exist. So let's go ahead and create that. This makes sense or final class, I'm going to create our UI image view one, give it a corner radius of Tony and say we need quick two bound to be true. And then going to return our ImageView. And that ImageView image, it's going to be sediment over the image has said, okay, we are also going to need a base view. Okay? It's going to go basically, there's going to be the hosting view for this image view. Because what happens is whenever you actually try to add shadow to the image view because it's because you are clipping the shadow does not. Clipping the view. Shadow does not actually exactly renders behind the image. So we're gonna do is, we're going to take another view, a sticker right under the image view. And basically bad base view is going to have the shadow. So that's the technique that we're going to use to basically drop the shadow for the imagery. We say private. What you've seen are. The shadow colored stuff as a UIColor, black color. Channel offset. What width and height is going to be? Points? Shadow basmati is kinda PTO 0.7. shadow radius is going to be ten. And it's going to be our base. And then we're gonna have our initializer. Now, this initializer is gonna call super dot init for grant frame as 0 racked. And this frame size is going to be basically defined once we have laid out our view. So don't worry about it like this 0 right here, because we are setting programmatically out. So this long gonna perform autocrine signal view. We're going to create a function to set up w. Instead of us kind of call center. Constraints. Wants to view the setup. Okay? Alright, well for the Setup view, we are going to add some peel. First base view. So we're going to add the base view on this shadow image view, right? And then inside the base view, we're going to add our image view as something. Okay? And then basically all we're gonna do is we're going to say for the base view and for the image view. And I run a four for each loop, for each view. And we say b dot leading anchor dot constraint equal to leading anchor and constant is going to be 16. So both of these are going to be, basically all the constraints are going to be same. All the anchors are same. So we going to simply put them in a for-each loop and apply same layout for both of them. Trailing anchor. Now remember trailing and grace negative value. Then you have your top banker. And last one is bottom anchoring. Okay? Let's go ahead and type this out and then we're going to see what the error is. Alright, so connected lines, okay, what's going on here? And S layout and prevented by that. And this layout constraint that activate and there's a letter B are going to activate our constraints. Lse issue, okay? Alright, okay, awesome. So I, one more thing we need to do is whenever B are setting the we are laying out the third UV to call this layout subviews function call super dark layers of use first. And this is where we going to actually draw the shallow bath. Every rather shallow bath is actually more efficient to draw the shadow for your app. So that's why we can actually provide the bat on which the shadow is going to be drawn. So we're gonna say RBI is viewed our layer dark shadow bands is equal to UI, mesial baths. And we're going to use rounded rect, which has a corner radius that we're going to say base view dot bound. So this is the rounded rect and radius SDN, and we're gonna say CG bath on that. So give us the CD bat. And we're going to say base, we dark layer dark should restaurants. So this is going to restaurants to view. And we're gonna say true. And base view dot layer dark rasterization scale is going to be the same skill that UI screen has. You ice cream, main.cc scale. Okay. All right, so with that, our shadow image, image view is finished and now we're going to head on to the new state will be a cell. That is our last subview, basically that we're gonna create, which is going to be representing individual cell, this cell right here for our view. Okay? So that is going to be best sort that thought we're gonna create next. 16. News App News Cell: All right, so let's go ahead and create a new file. And we're going to create, we're going to create a new table view cell. We import from UIKit. Alright. And we're going to create first our ViewModel, news. Viewmodel. And because say, if the news model was set, then we can extract it out. You'd think a flap. And then we're going to set all the other properties here. And discipline, we're going to make the network call trends in like, you know, other things. Okay? Now we need a variable for news, image data is going to be updater type. And this is also whenever good scientists called this object is set. We're going to say data, image, data. Right? We can have set the news image right here. All right, with that, let's go ahead and create our controls. So I'm going to have men, he may do. So. Lazy EUR. And we're going to use our shadowing rich. Okay? And here we are getting news image data set news image dot is equal to UI image data that VM extracted out. Okay. Now that is news image. Next we need title label. We're gonna set number of lines for this title label to be 0, so we can print multiple lines. And this is basically the title for the news. So this section right here, and this can be as long as basically the API returns there. So we're going to extend the number of lines to be 0. So Sandy can expand depending upon how many lions had needs. Okay. Now, how are we going to basically initialize? And we're gonna use the initialize overload bad. As that DXA cell style and reuse identifier, we're gonna first supply this information to the superclass is saying the style that he got and reuse identifier. Ok. Next, we are going to basically send the selection style, selection style for the cell to be none. So we don't show that gray light gray selection or dab highlight. We actually just are going to set it to none. Okay, next, we're going to call set of BW. Hi. This is simply a function which will set the strains. And we do need the initializer from the quarter being not gonna implement that. Now for the set of view, we are going to add some view. That's going to be the dipole label. And then you can constrain. So image constraint. Here we're going to have meals. Image dot leading anchor, rod constraint equal to leading anchor, news MH, trailing. And our news image is going to have a height, which is equal to a constant. That height it's going to be 200. And then your title. We're going to have trailing. Leading is going to be leading, trailing is going to be trailing anchor. Negative 16 dot banker is going to be basically News image. The bottom anchor in there, it's going to be 8 of gap between those. And for the bottom is going to be the bottom maker with negative 16 as the constant. Okay? And with that, our news TableView cell is also complete. So next up, we can now put all these together inside our ViewController and construct our TableView. 17. News App Safari View Controller: Alright, so with all the components in place has got to be rather easy for us to put together this view. So what we're gonna do is first of all, you're gonna need to import Safari services because we're gonna be using SM Safari ViewController. And best where it's actually defined under suffice or resource module. So cosine, again I included, alright, then we are going to need to create a, a, an object for our view model. So we're going to create a new model object, news less to new model. And we're going to create a lazy who are property for our header view, which is going to be header bu. The bill that we have created. And simply return, create that view, header view of font size 32. And we're going to return that. Okay? We are also going to create a. So these two can be private because you don't need to give access to these and where privately, the bar table view and this is going to be UI table view and UITableView return mu and V dot translate is equal to cos. I said that they will footer, we'll do UIView, so we don't have orderable you showing empty cells and we're going to register a class. And this is going to be basically our news. They will be USL news table view cell class dot itself. So we're gonna give it Stipe. And our view model has the reuse identifier. So we're going to use that reuse identifier to register, register that cell you're going to create. We can extend ourselves or other delegate and datasource. And yeah, so now the compiler is complaining about these delegates and art being our ViewController not conforming to these delegates. So let's go ahead and create an extension or ViewController or UI table view delegate and UITableView data source. And you can have number of rows in section. And here we're going to say touch returning View Model dot news, ViewModel.com. Okay? So that will give the number of rolls and then cell for row at index path. And basically this is where we're going to construct our cell. And we're going to say they will view DR DQ cell with re-usable identifier for index. And we're going to say this is going to be ViewModel dot. We use ID for index path. And this is going to be as news table yourself. Okay? So we're going to return cell. If we cannot extract or dQ, new steel, will you sell out? Then we're gonna return an empty cells. So UI, table view cell, like so. And here we need to do is get the news. So we're gonna say if you model dot news, we want to get the news for that index back dot row. And we're simply going to set the news model to that news item that we have extracted out. Okay? And that is basically going to set the news, okay? Now there's one thing that I forgot about. They will sell itself is the VR. We did not set this news be mouths. So let me fix this. I just realized that we are actually creating all these things, but we are not setting him anything. So our cell is going to be empty despite data meaning there. So we can simply say dido legal dot dx is going to be new to BAM dot title. Okay? And, and here we're going to make the call to get image. So we're gonna say network manager dot shared dark image. And we're gonna get the image from news for the URL string from news ViewModel dot URL to arrange. And this is going to give us a data back. Now this data is we are that we're going to use to set the image. So we're going to first say guard. Let data equal to data. Else. This batch Q dot main.js ink. So you're going to move to main thread. And once we get the data and we're going to say self dot image, dot image is equal to UI image from data Excel. Okay? So that is going to make sure that we have data are being downloaded, image being downloaded, and we actually display that into the cell. So continue forward into our view controller to our solely set. Okay. So our error is gone now, okay, and we're going to come back to the viewDidLoad function and we're going to set set of view function or call center be function which does not exist at the moment, but we're going to create that. And we're going to call setup constraints, right? And we are also going to call fetch news, a function. That is going to fetch the news when the view is loaded. So we're gonna call this news. And there's fetch news is gonna call our view model. Models get news and good news gives us a completion. And we are simply going to call Table View Reload here or not respond to. Rather, we load data, okay, whenever we get their news. All right. So for the set of you, we're simply going to, first of all, we're going to move this guy into our setup we call. Okay. And then we're going to add sub view, our header view cluster, and then our add subview. Okay? But the constraints for hair began as a NSLayoutConstraint dot activate. So we can use CAPM Layout Guide. And we can say in concert, and so those are going to be the header related constraints. Then. Constraints. Alright, so that is going to set all of our constraints. Okay? With that, Let's go ahead and try to run this. Alright, so if you notice, we have our images showing up, but they're looking rather ugly. Reason is, I actually miss pipe. This to be scale aspect fail, instead of which I should have like time to fill instead of fit. Okay, so there we go. And as you can see, our images are loading just fine. And we can see all the relevant images and all the news articles here. Okay, so that's perfect. Now. Oh, so there we go. This is the case where like, you know, we cannot find the image. So we have this placeholder image breaking news showing up right there. Okay? Now at this point, we don't have the click event right here, the selection events. So let's go ahead and go into our view controller. And all we can do is we are going to provide a selection. So on the table view we're going to say did select row at index path. And basically we want to get the news article that was being Bowers being tapped on. So we're going to say News, ViewModel. Get the item for indexPath.row. Oh, you're gonna put the guard led for the URL to make sure that we can actually construct a URL. And we're gonna get the news URL, that's time. So we need actually the actual URL for the news article so we can launch it inside our web view. And next, you're going to create a config for Safari view controller dot configuration. And then we're gonna create our Safari View Controller, SF Safari View Controller. And we're gonna pass the URL and the configuration. So URL and config. Now we have a choice so we can, we can present this basically with the modal presentation style as a form sheet. So let's check out the forums feed and then I'll show you the other way where you can actually, you can larger than four screens. So present safari ViewController and immediate true. And we don't need this so we can just simply bad. Okay, so now let's go ahead and launch the app once again. And what we will do is whenever you have this downloaded news article, right, you're going to select that. So we're going to select it. And there we go. We are launching our web view inside a, inside a form sheet right now in case if you want to basically get this loaded in full screen. So you can say for screen right there or any other mode of modal presentation style that you may prefer. Ok, so when you launch it as a full-screen is going to basically launch inside this view and you have all the other options. Now, this is a fully functional browser right there. And whichever view you load is actually gonna show all the information right there. And if you notice like Safari view yourself, consider a lot of things. So when you start scrolling and actually hides away Safari view, so user gets the maximum view area out and as they scrolling up, the controls show up, show backup, right? So there's actually one of the, one of the nice thing I really like about about this S of Safari view controller. Alright, and with that, we came to the end when Henry have built an entire app, entirely news app with various different things that we actually put together. And hopefully you found thinks the interesting any learned from by building an actual app. So hopefully you found this useful. And thanks again for joining me in this journey and building of ZAP. So thank you so much. I will see you guys in our series. 18. Photos App Intro: Hello everyone. I hope you are doing great and welcome to this new course on photos app, where we're gonna be creating these photos app using API provided by pixels. So pixels.com is a website that gives you access to free photos using an API. How well, they also have a free videos as well. And basically, in this website, you're photographers go and upload their creation. And they actually providing an API that you can use to download that data or display that data in your app or whatever you wanna do with it. And they are free to use. So you can basically check out pixels. Pixels dot-com right here at pixel Sarkar. And you can see that I like you a whole bunch of photos. And hence you can see like, you know, there are videos and everything as well. They have a very well-written IPEA AA, and this API once again gives us access to all the data that there is. Okay? So the good thing about pixel is it gives you enough amount of data that actually works good for mobile use cases because it has a source for the API that actually gives you various range and size of images according to the need that you may have. Alright? So that's about the API itself that we're gonna be using to develop this up. Let's take a look at the average self. So basically we're going to be developing this app using storyboard. And storyboard. By storyboard, I mean the nars Swift you eyes to storyboard when your select when you're creating your project. Youtube's thrifty II for the user interface or storyboard. So you're going to be choosing storyboard in that case. So we can use UIKit, okay, and the code itself is going to be complete programmatic layout. So there's not gonna be any fire or nip file or a storyboards are kind of being used inside this project is going to be completely programmatic. And so you're going to be learning about bad. All right, so let's take a look at the app itself and then we're going to talk about learning objectives from this course. Okay? So this is the app. We are going to display images downloaded from pixels API on the on the, on our app in a TableView. Okay, began and display who the who the photographer it and they're DAG or handle. Okay. And when you tap on the folder itself, you can see a excuse me, a portrait view of their photo ID and they're going to be displaying a landscape image, our landscape photo. So that's where they think it's gonna be. It's gonna come handy. You have portrayed and landscape both of them available as a source for the URL. So EPA yourself gives you access to those two. So we're gonna be using that. Next thing you're going to be, you're going to notice basically we're going to develop is going to be infinite loading. So if they, if we keep scrolling, the new, new images are gonna load at the bottom. And our users can keep scrolling to explore more images. So there's only itself is a rather complex app. And basically there are some learning objectives. First of all, the entire app is fit and programmatically so there is no use of UI or drag and drag and drop based UI construction, so there's no storyboards are nuke, so you actually get to learn how to career programmatically out in Swift. We are also going to be creating abstract networking layer, which basically gives you access to generic based networking layer that he can create a generic solution that can be basically used in any of your app. So you can literally take those files and drop it into another project and start using those. And it'll simplify your networking layer and efficiently manage decodeable and everything is generic base so you wouldn't have to code over and over. You're API client. Okay? So how are we going to begin to see how we can, how are we going to basically develop that? And we're going to use endpoint management using enums. So we're going to be using enum, not for just four switch case and stuff we're gonna be using for endpoint management and begin to take protocol oriented approach to basically create protocols. And we're gonna see how we can extend those protocols not only within strengths, but within enums as well. Okay, and we're going to be using Swift generic so you can learn about 15 Eric's. So that's gonna be your entire networking part, API part. Then you are also going to be learning MVVM design burden. So basically how Model-View-ViewModel design pattern works and how you can actually leverage MVVM design pattern to create lean ViewControllers. Okay, so you view controllers have limited or just the right amount of control. So they are not doing too much on behalf of your view or on behalf of your model. So we're gonna see how we can keep our view controllers like, you know, lean. So date only perform enough task, which is the communication between model and the view. Alright, so there's gonna be another learning objective for this course. There are a few more. So one of the most important thing dealing with table views and working with images is efficiently loading images on debug view. And I cannot stress enough how important it is for you to understand how to load images and deal with you. Because if you've worked with images in TableViewCell, you know how hard it is to basically display an image inside a cell in whenever that cell reuse happens, that flickering or loading of Fromm images and stuff like that, that all happens within TableView and it's quite a challenge. So we're going to be learning how to develop an efficient way of loading images hint table. We'll be going to be loading all the images from network. So you're going to learn how to load network images. You're going to learn how to asynchronously load images and gashed them. Ok. You can learn how to handle downloads, ImageDownloaderBRS, and cancellations if there is no longer visible. So you can prepare the cell for reuse within tableView. Okay, you're going to be learning how you can leverage infinite loading of the cell. So whenever a user scrolls at certain point, you can learn more content at the bottom. So your end-user and there are runs out of content. So that's kinda be another thing that you're gonna be learning. We're going to be using delegate pattern at all in this course to propagate events. And if you're going to be separating out the view from ViewController. That way we can manage views state separately and ViewControllers state separately. Ok. So there is a lot in this course that's jam-packed and we are going to be creating a production quality app. So basically going to be learning how to create a production ready app. And these concepts that you're going to learn, you can apply these concepts in your next project and you show, we'll see that a lot of benefit and Reuse comes with those things. Alright, so I hope you're excited to join me in this course and learn more about how to better architect your apps. Okay, so I will see you guys in the next video and we're gonna get started. Thanks for watching altogether next video. 19. Photos App ProjectSetup: Hello and welcome back. And in this video, we're going to start our project. So what I've done is created an empty project and while creating the project. So let me show you if you go file new project and you choose app. When you click next. All right, and you click Next. This is where you enter your product name, your team ID, your organization name. And then here, this is the place I was talking about. So interface, UI kit based interface, apple still call SERT storyworld. So minded Lake in our v-not cannot be coding anything in stories, in storyboard bios, but still called storyboard. Okay. So you're gonna be choosing, storing poor and not safety I in the lifecycle is going to be UIKit AppDelegate lifecycle. So when you're creating the project mixture, you select this one. Ok. So once you have created the project, the project is going to show up with this standard template. So your Xcode is going to create this for you. So next thing what you can do is basically go into the main storyboard. So select this file and simply deleted. Okay? Because we are going to be launching this view controller programmatically. Alright. So that was the first thing. Second thing you need to, excuse me. Second thing you need to do is go to info dot P list. And in the info.plist you see applications seen manifest. Okay, so expand that. And once you expand that, you're gonna see scene configuration, expand back to application session, role, expand that. You'll see items here and there. And as soon as you expand out on, you will see storyboard name. So we need to remove this from here as well. Okay? And st. So, so basically this insurance that our app is not going to try to load main.storyboard, but it'll try our programmatic way, OK. Now, last thing you need to do is go to your project settings and general main interface tests the room. Just select main and remorse and hit enter. Okay, save that. And that's about it. Now, how would we go ahead and launch the ViewController that we want to have as an entry point. So I'll show you right here, but we didn't delete them. Fault ViewController and Create a new view controller, Home view controller so you know, or which you couldn't do. We wanna launch, okay, so first thing, what do you need to do next is basically go to your scene delegate. Now your scenes are, your app is managed using scenes. So it's composed of seniors. On iOS side, there is only one scene that you see, but if you use iPad or MacOS, then scenes can be replicated. So you can have multiple scenes for an app, okay? So you're gonna go to defection. Scene will connect to session. Okay. Here you'll see this guard led underscore, C-H-E-N windows scene. So for this underscore and we're simply going to say, this is called Windows team. Alright? And then we can create ViewController variable. And we can assign view controller into this. So we're going to initialize it. You controller. And this ViewController is district ViewController class right here. Okay? So you're gonna initialize this ViewController and assign an object. So we're going to create ViewControllers object, okay? Once we have created this object, we're going to use window. Okay? And we're gonna create our window. So you're going to say UI window from scene. So Windows scene. And we can say window dot root view controller is equal to ViewController. Okay? Now this is, this last step is most important to make key, make this window as given, and make it visible. Okay? So in order to see where you have everything working properly, you're not going to change the background color for our view to read. And let's go ahead and launch this inside our simulator and see if we can see a red view controller. So it may take, for the initial launch, it may take a bet and they go, you have your red ViewController launching. That means our programmatic initialization is successful. Ok, so that is done. So let's go ahead and remove that, that color, red color. And as soon as you create it, you can delete. And then notice that your view controller is created with background color as black. Okay? So we can simply set the background color to white. All right? Okay, so we are, we are done with this one. So what are we going to do next is I'm gonna create a few folder. So let's go ahead and start creating a ton boulder. So we're going to need folder for ViewControllers. So view controllers where you're gonna need. So just select, right-click and select New Group in any order for use. Ok. And then need folder for models and, and a need for view marbles and one for networking. Alright. Okay, so we're going to remove deaths. So delete, predict, we're going to create a new folder. So now for these files, these are support files. So what I'm gonna do is I'm going to select these and set them in a new group without folder. So this is going to be the watch your folder. So I'm going to call this a support miles away so they can effect. So I'm going to manually more D's. Okay. Alright, so at the end, this is what you should see. If you try to build your app, you're gonna see build fields because we have that seemed element. It will chance there's ViewController missing, so we're going to fix that. So let's go ahead and right-click on your ViewController. Add a new file. And you're going to add a new swift file. You can add a swift file or you can add a Cocoa, Cocoa Touch Class. And Cocoa Touch Class Takes a base view controller class that he can actually create your object from. So let's create Kauket engine desk. And I'll show you the either case in next class creation. So you're gonna call this Home View Controller. And we're going to simply save this so we can create, okay, so our final it created. Okay. Now if you notice there are few things that controller needs. So the controller inherits from base class UIViewController and had viewDidLoad. Okay, so next time when you're creating a file, you can simply choose a file and write this out yourself. Alright, so go to your scene delegate and changes to Home View Controller. Like so. And come back here and set you dark background color is equal to Y2. Okay, go ahead and build it again. And you should be able to launch the app successfully. Okay? Alright, so, so now we are able to launch this out programmatically, so that's good. Next thing we're going to work on is going to be models there. So we're gonna create models for our photo feed. And for that, we're going to check our PPA. Okay. 20. Photos App Models Creation: Alright, so what we're gonna do in this section that is basically we are going to sign up for a pixel. So I've already signed up. So you simply go to pixels.com. So Bxy ls.com and go ahead and click join to basically showing it's a free registration. All you need is your email address and then you'll be able to create your account. And once you have your account created, there's gonna be a confirmation email. As soon as you confirm your email, you'll get an API key. So once you get the API key, your God do documentation section, it'll show you like you know, as you get the API key bed documentation is listed there. Ok. So once you have the documentation listed, you, your land on their screen when you click on that link. And this link has a whole bunch of things. There isn't authorization. So I'll talk to you about authorization in a in, in the video itself, how to do that, but Authorization, essentially, the way it the way it goes. So let me show you, okay, so authorization is an authorization object. By the way, this is my key. So please don't use it. Please register because it's absolutely free. Can't go ahead and sign up and get yourself an API key. But once you have register and got the authorization, authorizing, the way this app APIs authorization work is you need to set an authorization header, okay? And provide the authorization key inside that header. And after that, if you make a call to the API, you'll be able to request stuff from the EBI so you'd be able to start getting respondents. You're not gonna get for one or another tries air, OK, so make sure to get your API key right. Then. We're going to look at photos objects. So there is going to be the photo object that actually tells you about the photo itself. Or what are the things that API provide us, right? There's only going to be few things that we are going to be interested in. For example, we are going to be interested in ID. We're not going to be interested in in these in this case. I will not be. But if you are interested, police for intrusion for that, there's a URL. So in case if you want to provide a URL back to pixels, then you can use this URL. So you can have a functionality there, user apps on the photo, and they can check out this photo in a web browser or something. You can have that do. Ok. So that's why URL if there, then you have the photographer who took this photo and photographer us URL. So photographer itself, their profile. So you can have that too. I'm in your app. Okay. So for our case, we're going to be needing ID photographer just for the name. And then we're going to need the URL, but we're going to only extract apart off after at. So they're St. Die of section. We're going to take it out and create a atom or like art Dag for them. So we're going to call this photograph or tag, right? So we're gonna see how we can do that. And then we might need basically, yeah, I definitely need for that size. So basically say the source. And this is in other object. There has portrait and landscape badly. So we're going to create another class which is gonna contain these two. So we can actually create this whole thing, quarterbacks today. If you notice this all response, all this guns in basically with the feeder assault. Ok. So let me see. Okay, so let's look at the curated. So we're going to be, so I'm gonna show you how you can use enum to provide different values. So if you wanted to search for photos, you can add a section if you are curated for those. This section B. We'll work on curated photos in this example. And there's gonna be a challenge. So for you, basically are going to be working on a part where you're gonna provide search for photos and other view controller that can be launched and the user can search for photos. Okay, so we're going to be providing port endpoints. But if you look at curated photons and basically yeah, QA photos or search for forest, most of them have similar JSON response if you look at this. So let's look at geared for growth and I'll show you how search for photos look like. So you have page you have per-page. So how many so page number, right. Per pages, how many results you are st on the beach. And then you have photos. And the photos is an array which actually lists out in individual photo object a bad he just saw. Okay, therefore dark object, this one. So in our API response, we need to code our model in such a way that it can take all these values, right? For so for afforded us, the only additional thing is dawdle result. Don't result actually gives you how many results are there. And then you have beach verbiage inwards again, four dots. So this tells me that There's only going to be 14 to feed result for potently in case I'm gonna create one of that. Ok. So with that, let's go ahead and jump into Xcode. And let's create this EPI somewhere, said this documentation aside. And alright, so now we're going to create our models. So right-click on your model's folder and create a photo feed results. So he so file called this four door feed result. Okay, and unleashing it's okay. Import foundation. They'll create a struct photo, photo IID result. This is going to be quotable. And we're going to have those bags are those fields that we saw in our documentation. So once again, pulling up the documentation, these fields, but you can type them ss. Ok. So you dive down at his desk and I give stability or give quotable ability to decode those. Alright. Okay, so total results page. So we're creating this object called photo, right? It doesn't exist right now. So let's go ahead and create a new file. So I'm going to press command to create a new file. And I'm going to call this photo. Okay? And this is going to be for the object. And here you gotta create struck again called photo quadrupole. Okay? Now, if you build, once he had the photo created, your build is going to succeed and complain. It's gone. That does object doesn't exist because now it gets. All right, so back to photo. We're gonna create ID photographer. You're gonna create a computed property out of our first URL. And you can now basically you simply return photographer a URL, dark. Replacing occurrence is off to begin to replace occurrences of string when something. So we, so let me paste accord him then we're going to talk about it. So go back to the documentation and I'll show you. Alright. So when you get your response right here for the object, when you get it for the object. There we go. Okay. Your photographer URL has outlined at the end, right, so we need to take this entire string and replace it with a space or empty, basically no space. What this is gonna do, it's gonna basically just get their spark of the of the photographer's name. Okay, so if you're extending this app to basically provide photographers cryptographers profile, then what he can do is you can create this. They can keep this as a base URL and then append the tag two basically generate the URL for the alpha. Okay, that's how you can do it, right? So remaining everything else is yeah, it's pretty self-explanatory, so I'm not gonna go into detail of that. So let's go ahead and set aside the documentation once again and go back. Okay. What we need is basically the source which has the photos, a size of the formula. So I'm gonna call this for dose size. Okay? And this object is not created, so let's go ahead and feed that at all. Okay. So photo site is gonna have led to a better portrait. Landscape is the one that we're going to use to display in the table view cell. So going to display a photo in landscape and TableViewCell. And when we use our data photo, then we're gonna launch AS portrait version. Ok, so that is something that we're going to go ahead and build. And you should be able to build now, okay, so now our models are ready actually. So we have photos. We have photo feed that actually gives us the entire response. We have photo photo sites. So so all of these are more models related to the response itself. Now, how about the response itself that the response that we are going to get? How do, how are you going to handle? How are we going to handle the base URL? How are we going to handle the URL construction and stuff like that. So that is going to be next. We're gonna create one more model, but that model is going to be related to networking gold. So let's go ahead and, and look at the networking part. And then we're going to create some protocols and we're gonna create one additional protocol. Do handle the endpoint management using enum. Okay. 21. Photos App Networking Endpoint: All right, so in this section we're going to see how to manage our networking part. So right click on your networking and basically launch your new template, new file template wizard. And we can ask select Swift File and more time. Hit enter and we're going to name this file endpoint. Ok. So this endpoint is going to be a protocol that is going to provide base URL path for the, for the EPA and any query that you might have. It'll also have an API key. So this is going to add the header, Create URL, basically for the API and create a request. Okay, so let's go ahead and look at that. So we're going to first create a protocol. You're kinda call this endpoint. And this protocol endpoint is going to have eight BCE forgettable property bath. Okay, now we're gonna extend this protocol. Read extension. And essentially the way to add more functionality into your protocol or provide default implementation. We're going to add a bit more for shouted into this. So we're gonna create an art header. Now, if you know about protocol, you know that Protocols don't allow any kind of definitions within them, right? Recall body itself. But if you need to have a definition or default implementation, you should always include it in your extension. And he can only include in any of extension at this point. So surf restricts you to provide any kind of definition within the protocol. Definitely vertical and declaration yourself. But you can use to extension to provide default implementation for those, these implementation still over writeable. But they give you a default way where your user does not have to implement them if they don't do, okay with that. First variable. First property that we're going to need is going to be okay. So off header is basically the API key, the API key that hints given to us by pixels API. So we're going to need that. So I'm gonna create a new file here called API. And this file is going to have the API key. Okay? And you're going to have static lead II. And your API key is going to go there. Now I'm gonna put my API key and I'm going to jump back into. The end point. So you go ahead and grab your API key populated in there, and I'll see you in Endpoint class, endpoint structure once again. Okay. All right, so hopefully you were able to finally EPA and you're able to put it. So when we have put the API key, we can simply return for the Altair, the api dot like that. Ok, now here we are also going to create a URL components, your L components. Okay? And this is basically going to help us construct the URL. All right, for the baseURL, we're simply going to say take the bait and that has been declared inside the endpoint. If nothing is provided, just create empty oil component and then say component dark bath is equal to bath components dot query, query, and then return that. So next, we're gonna create a request URL components. We can construct a URL from your normal components. If URL is not data, I'm just going to die at some dummy URL so you can put your fallback URL here. And I see for the request, gonna create URL request object passing URL. And for the request, we are going to set, you're gonna force unwrap soon because this one is going to generate optional. So we know that we are passing the string so we can actually worsen right down. And I'm just gonna say result dot set value. And this are they going to be, we're going to set the art header. So we can just say Arthur header for field authorization. So it's going to be the Authorization field request header. And we're going to return this request. Okay? Alright, so this is the endpoint. Now, like you mentioned in the last section, that we're going to need one more model. And this model is going to be an enum. There's, this model is going to provide us a way to basically choose between search by category, API or curated. And it's also gonna provide endpoint obese URL, the bath in the query. Okay, so let's go ahead and create a new file in the model. And we're gonna call this one photo Vdd. Ok. And we're going to create an enum here. And we're gonna use enum to basically provide us, provide us dysfunctionality of choosing between two categories. So just going to be a keys search by category. Okay? This is going to take two associated values. It's going to be category of type string and per-page int. So basically, when you are building this search by category functionality, in that case, you're going to provide a category. And you're going to provide how many items per page you want, okay? For the second case, it's going to be curated. And this is going to take current beach int per page, int. Okay? So these two associated values it's going to, It's gonna provide. Now you're gonna create an extension on photo feed itself. And this is going to extend that protocol. Now, protocols, can we extend it by prognostic nation can be provided by enums as well. Ok. So now you're compilers can say type for a free does not conform to protocol endpoint. And we do want to do conform to protocol. So I simply say, okay, fill in the blanks for me. And there you go. You have your BCE URL, string creative silicon assembly. Return our baseURL four pixels. So baseURL four pixels as EPA dark pixels start gone. So I'm going to paste it right here. For the path, we're going to put a switch statement here. And this switch is going to be on self. Ok. And there are gonna be two patterns to follow. There's going to be one which is search by category. So I don't need any of these. But this case, so I'm simply gonna return because I'm only creating the endpoint and I'll leave. So right now I suddenly bath so you don't need the other associated relative parameters. By the way, you're going to need those in the query bark. Curated. Once again, take these things out. Return Curator, Okay. Now the query part, this is where the query comes in. So if you go back into the documentation for the curated, you're going to notice that the query is right here. So this is the query takes SGB api dot pixels.com slash un Curated pourer page, write it equal to one, so one record per page. Now, you can change that. He can also pass so that request okay. So you can pass for the perimeter, you can pass per-page. So default is 15. If you don't pass it, you are going to pass it. And the page number, the number of page you are requesting. So we're gonna basically used as to increment, increments to get like second based or beige and stuff like that. So we're going to pass this one as well. Alright, so go back to our Xcode. For the query. We're going to once again put a switch statement on self search by category. Now here we are interested in Soviet associated values. So I'm gonna type or category, so category that you can then select in part by h. Okay? And this is going to return a query which is equal to category. Hand for pj is equal to polar page. Okay? So this is going to return for search by category. For curated. It's gonna allies again, take, so let me get told E. And we are going to remove this and simply say let current page per page and return. So I'm going to paste it, paste in this code. Return Page is equal to current page. Per page is equal to per-page. Okay? So that is our query, which is going to be, so when we request this enum dot query, it's gonna, for a curated case, it's gonna give us the query API with beast in Bath and everything, making her with the numbers that we have. You had a question. Okay. So that is the next part. How are we going to actually dark about? How are we gonna get the endpoint working so it can provide us the entire URL. And you're gonna see basically, well, I mean, affecting the response. If you look at your endpoint right here, in your URL component, you're already using these components. You're still, you're gonna see base bath and query. So sorry, I didn't debate. They could piggyback you already. The end point right here is what we're going to use to call. And photo feed is going to provide us all this information. So we're gonna see photo freedom for the feed dot requests and stuff like that. It's going to construct that by getting those properties that you have created right here for the base, for the path for the query. Because that URL is being constructed right here, that are questions being constructed right here. So in order to construct this year requests or you can have a URL component, your urine component already to quests the base, which is four a year photo feed case is going to fly, do pixels for the bath is gonna provide. We're going to be interested in curated, but murderer pads here of basses can provide that query, whichever query Battier for wider query you have parade curated our search by category. It's going to provide that. So you're gonna get all that information right there. Okay. Alright, so this is setting up our endpoint. Alright. So let's go ahead and look into our other networking related components. 22. Photos App Generic Networking Client: All right, so in this section we can have create our generic networking layer that we were talking about. And next few files that we're gonna create. The files that you can literally take them and drop it into your project and see and basically work with networking. So let's go ahead and take a look at them. So I'm gonna create and run networking section. I'm gonna create a new file and we're going to call this one result. All right? So this result is going to be an enum called result. And this result is going to have to genetic types dn you. And you're gonna say where you err. I'm going to give an, give the dying for you. That's error. Then we're going to save, in case of success, we're gonna bass t. And in case of failure, you're going to pass you. Okay? It's your generic result object that we have created here. Right? Now. We're gonna use this inside our other classes that we're going to other strokes that you can accumulate. Okay, so let's create a new file. And we didn't have call this one API error. So basically these are the errors, error cases that you may encounter, like orange APA may encounter doing these networking sessions. So you're going to create an email for that to capture them properly. So EPI error, you're going to have request failed first one. Invalid. Data is both unsuccessful. These are the error cases, the EPA error cases. They'll get a track and you're going to create a localized description property that is going to provide a localized description, a string-based description for these areas. All right, so the guy simply return what this editor is. So in our case, we'd simply going to say just what the error rate. Okay, so this localized descriptors for writing a localized description for all the error cases that that'll be generated. Okay, we're gonna create another class or another stripe. And this one is going to be API client. Now, API client is going to be a protocol. I mean, we're gonna create a new file and we're going to provide the API client protocol. Okay, so let's go ahead and create API client. And this vertical is going to be a generic type. So Protocol API client, okay, it's going to have session, which is going to be your URL session. Get involved property. And it's going to have a function called fetch. Okay? And this is going to be taking a pipe decodable. So it's going to be a generic type D chord evolve any decoder both dipole will do. We're going to expect request parameters can be passed in. So URL request began to have a closure, basically for decoding itself. So you're going to say, this is gonna give us a portable object. And then we can have a completion. And this completion is going to give us the result. So this is your API client protocol. Let's go ahead and check it out. Oh yeah, there we go. Okay. Rebuild everything, so shuts should succeed. Okay. Now we're gonna provide an extension for API client. And you're going to create a cluster, you're going to create a diabetes for our task completion handler. So this is going to be. The quotable, API, air. Just go down her turned away. Right? Now. He can then create a fire private function decoding task, which is gonna take genetic type D of type decodable. Web request, request, decoding type. If you dot type. Now the stereotype is the decoding type because your decodable object takes the type itself, right? So with DDR type, we're going to get the class or struct that decodable type name itself. Okay? Alright, with the completion escaping case on task completion handler. Okay. This is going to return URL session. Ask us, okay. Now we're gonna create a task session dot beta task, right? And we're going to generate a task from the request. So her quest that had been passed in to us right here. Okay. And we will use the completion that gives us access to data spawners and air. Okay? Now we're going to check. First thing is if we can cast the response in do HTTP URL response or not. So HTTP response. And here, if he can't, then we're going to pass the completion back with nil request failed. And we're going to return from here. Now, if the SGP response status code is 200, everything is okay. Then you're gonna try to get data. And you're going to wrap this data and do, do it. So generic model that we're gonna get from JSON decoding. So we don't say J San Diego dot decode. And here we're going to say decoding type. Who our decoding type is, the type that has been provided to us with a t week and whatever D is, begin to get its type with a decoding type, okay? And this is going to be from data. Okay? For the completion, we're gonna pass genetic model back. I'm getting cash hip, there's anything bad. Pass completion with nil and they JSON conversion failed. Okay. What else case. Oh, Shapiro, put equal sign. Okay, the else case going to simply provide a completion with invalid data. Right? And for the last else gaze where HTTP response, it's not 200. We can provide a completion with nil bonds. Unsuccessful. Okay? At the end, we're going to return task. Okay? So there's our brain function that's going to be used inside our fetch functions. So let's provide a default definition for a fetch itself. All right, so this meter signature right here. Instead of typing in holes, bang. There we go. And remember we talked about like, you know, how protocols can have default definition. This is what we've provided here, providing, we're saying making a fetch has, it'd be a client has this first function returns a default implementation, which is right here. Now once again, we are going to create our task from decoding task. So helper function. And in the temporal function we're going to pass our request and the type to yourself, okay? And this is going to give us a JSON decoded or air, right? So we're going to simply say dispatch, queue taught main dot async. Okay? And so let's get to JSON first. If there's any issue. If there's error and B got the air then began, there simply were done that in the completion. Otherwise, we are going to return. But well, if error object is not nil, then we can then going to return the error optic yourself. Otherwise, you're gonna return result dot failure, invalid data because we could not get the data right. We're going to have any return right here. Okay? Now you're gonna say if let value that means can we decode the JSON that we got? Right? Can we begin decode that? Then we're going to provide that in the completion inside success. Otherwise, we can simply call completion failure. Json parsing failed. Okay? And once again, right here, we're gonna save to ask dark there zoom. So this time we're going to resume our session task. Okay? So what once again, this is going to do is basically we are going to get a decodable object. So this decode task, decoding task handler is going to help us basically, first of all, make the request. So we are making the URL request here that beause spear calling the API, right? We are getting the response in. We are basically finding if the response is okay, if responses okay, then we're going to create a generic model out of that. And that model is going to basically decode that tie for us according to the type defined. Okay? And that decoding task is basically called inside our phase function. So we have just broken down this URL session task into two different functions, right? So this is going to basically called a decoding task a and the decoding, if you notice, and the decoding type, it's a completion right here. This guy right here. It actually gives you access to the JSON. If the values there, that it gets that from the, from the closure block and it assigns that value. So we can actually bath that inside the completion. So what you're going to get is the model itself for your API call, right? So you're going to make the API call and you're going to get your model populated, ok. Now, these three files, result APA, error in API client are generic. So basically you can take them and drop it into another project and started using any electrical air. Now, how can you use this? That's the topic for the next section. 23. Photos App Concrete Pexels API Client: Alright, so let's talk about how to use the tibia clank. Okay? So what are we going to do is we are going to create a new file. And we're going to call this file pixel Pixels client. And once again, important foundation is okay, we're going to create, he has clearly a final class. Pixels client, API, client. Okay? You're going to create a session, URL session. And you can have initializer, initializer. It's going to take a config URL certain configuration. And we can just say self dot session is equal to. And we're going to construct our URL session based on the configuration that is growing it. You're going to have a convenience init as well. It is simply going to call self dot init with config default. So with the default session, if someone costs initializes the zone, then we're gonna create and he felt testing configuration and you're gonna create your URL session using default configuration. Otherwise, they cannot provide the assessment configuration. Okay. Now, we're going to create a function that is going to get photos for us. So we're gonna create a function, get photos. Okay? And remember, API client already has implementation for all of its functions. So on only function that it needs is, if you go back, is it only nice PHET function session is something that we're going to have to initialize Viennese shy during that phase, function has a default implementation, so we don't need to worry about providing a default implementation unless you think that you need alright, this, okay. So you're going to create a function, get photos. And we're gonna get this from Porto feed. So gonna say photo feed type pipe is going to be Photo feed. Once again, the reminder for the reminder photo feed is the enum that actually provides us two cases, search by category and curated photos. Okay? So we're expecting that and we have a completion result or don't feed result. And API header. Okay, this guy is going to call French function. And we're going to create out of the photo feet. You're gonna create a request. So this is where we were talking about how we're tying everything back together inside the endpoint, right? So when you cleared the endpoint protocol, you create. This endpoint has so many creates endpoint protocol or extended endpoint protocol. For example, inside your photo feed, right? At that time you providing base path. In query. These definitions. Your endpoint itself has this URL component. And request URL component uses these base path in query to construct the URL itself, right? And this request is the one that actually creates the request for you. So if you call this request, so right here in pixels client, we're saying photo feet type, right? Dot requests. So it's calling this request is collecting all the data are everything that we need for to make this request. So it's collecting the URL with the base path in query rallies. And then it's also collecting the OS header. So setting the Altair and returning the request itself that we ultimately pass into our API client. Okay, now we're past that rate and we got JSON back for decoding. So you get that JSON into our decoding. And this is going to be auto feed salt type, right? So we're going to simply say guard, let FOR DO feed and so on. This juicer here for door. Oh, yeah, we're going to cast this JSON and try to guess this JSON into that. Otherwise, we can return nil. If two gas with successful, then we're gonna return photo feed result. This guy right here. And I'm going to call our completion. Okay? Alright, so this completion is going to basically have your afforded Fenon result, okay? And if there's any error, we're gonna get theatre, right? Okay. So get photos is gonna call the whichever type of feed that we are providing. And that's how you can use your API client. Okay, so once again, all we're doing is passing the, getting our feed type. In, getting the request out of that, we get the JSON in decoding. So we get the Dakota JSONP tried to pass it. Okay, we want when we parse it, we get the completion. We passed at completion, player back to the caller of get photos. Okay, so that's how we can use the API client, right? So now we are actually ready to start looking this into, or let's put this into a view model. And then we can see how to use this or how to call Pixel client.write, get photos to get the photos out of pixel API. 24. Photos App Photos List View Model: Alright, so let's go ahead and create our ViewModel. So we're going to create just one model for list. Then I'm just gonna cry, click on the View Models folder and select the swift file. And we're going to call this one auto, lest you Marble. Ok, how we are going to import from UI kit this time and we're going to create a final class photo list. Remarkable. Ok. Now this photo list, few marble is going to have a photo's available which is going to contain all the photos. So it's going to be an array of photo. Okay? We also need some way for our ViewController to know when photos are loaded. Okay, so we're gonna use delegate pattern for that. So we can simply create a protocol. And we're going to create it. We're going to name it photo less ViewModel delegate. And the function that's going to be there, the only function that's going to be there is going to be for those loaded. Okay? And we're going to create a week variable delegate option, okay? And now we're gonna create our client. So pixels client, right? And there's pixels flank is basically going to download these photos from the EBI. Okay, let's create another variable called current page. And during the initialization or for the initializer of this view model. We are going to initialize our pixel client. Like so. Okay? And we also call a function called load photos. Now this load photos is an OB and internal permission. Or actually begin to get, let's not leave it open for any further ViewController to call. So this load photos function, it's basically going to utilize our pixel client to get the photos. Okay, so let's go ahead and first thing first, because our current reaches 0, we're gonna basically increment and the current page. So whenever we call this load function, it's going to increment the page. So we are actually assuming that that user has crawled to a position or it's a first-time requests. So we're going to actually increment a page and then make the call to the client. So the same like you know, the page number as 123 and so on. Okay. So herein granted, the current page. Now you're going to create our feed is going to be photocopied. We're going to use curated version of photo feed. Current page figure I supply the current page value and per-page number of results. We're gonna say we want 20. So we want 20 photo, 20 photo results from our API. Then we're gonna say take our pixel client object that you have created and call get photos here from feed. This gives, this gives us a results. So we're going to take the result. And we also going to capture self. Person going to do is we're going to try to get self. All right, then you can switch on result. And we have two cases. We have success and which gives us the feed the photo feed result. So 40 feet result. Yeah. And then we say colored a lead for DOE, result from photo feed, result. Otherwise return. So you wanna make sure that we get for the feed that for those result. Ok. And then we're going to call strongSelf and set photos dot append. So you're gonna append. And we want to append items. So you want to use the overload that takes contents off because this takes a sequence and we're gonna say photo, result, dark photos. All right, and we're gonna say strong self delegate, dark photo loaded. So you're going to call our delegate to letter delegate implement or know that hey, we have new photos loaded so you might want to refresh yourself. Okay, next case, which is the failure case, we're going to get the air and print the error like that. Alright? We should still be able to build and build, build should succeed. That means everything is looking good. Okay? So we need to have you've got initializer. Now we need a way for our TableView that because this is going to be utilized by TableView, are tableView needs a photo at index. So all we can do is we can basically give a function that can return the, return the index, and we can create this. We can make this photos as private. So you're going to create two functions. So table, our table, we need to find two things in order to act as a data source. So basically, TableView datasource needs count or number of rows that it needs to be, needs to be showing, and the cell at index. So we're going to create two functions. One is going to be Count R. This can be a variable count. And this is simply going to return photos dot count. And there's going to be a function. And this function is going to be good for TO PAT index. And this is going to return a photon. Okay? So what you're gonna do here, simply return photo from that index. Alright. So with that, our ViewModel is partially ready there, like in a couple of more things that we need to do, come back and do it here. For example, when we are ready to load images, we're going to basically create some functions to load images. But let's first out. Unless first test out our API calls to see if they are working or not. Ok, so in the next section, in the next section we're going to basically see how we can take the ViewController and make an API call and see if we get any results back, okay? Alright. 25. Photos App Photo List View: Alright, so first thing we're going to do is basically check if our view marble is returning a response or not. So let's go ahead and try that out. So I have a home you control or open. And you're going to create a URL object here. Photo ListView orbital. And then we can have basically assign the delegate, soap delegate for the view model. And we're gonna say extinction home. You can told her worklist, we'll model delegate and we're going to implement a delegate. There we go. Okay, and whenever our photos are loaded, you can then get the get this delegate method called and we're going to be able to get the access to the folder. So let's get one photo. So get photo at index 0. And for this, we can just print photographers plus name and URL. This also print back, okay? And with that list cornered in from this. And then go, so VR, getting photographer named here, URL and its stack so badly. So our API call is working just fine. That's awesome. So let's now go ahead and I'm going to remove this test code. So, you know, everything is working fine. So let's go ahead and start writing. Are we going to her? Okay, so what we're gonna do is instead of having your TableView and how the delegates and everything built out here, we're going to build them inside another file. So we're going to call this one for the list view. So it's going to be another class. So you're going to simply create a Swift file photo list. You. Okay? And inside this photo Foreign Minister, you begin to create our table view. And, and basically the table view's going to host a cell and our MOU modeled and everything, it's going to be contained here. So as coordinated import, UI kit. We also then to create a protocol soon begin, propagate the event. For example, selection. For the selection, we will let our view controller node that photo it's selected. So we're going to simply create a protocol for that. So we're gonna say photo list, item, selected item delegate. And it's going to be a class inheriting class. And then we're going to create a punk selected photo. It's just going to take a photo. So basically it's gonna give us the access to photo. Now we're gonna create our class for dualist view, UIView week, our delegate, foretold list, item delegate. And we're going to create horribly modeled. So the Vbar, you normal, put doe u. And we cannot make this bu, hey, delegate corner to put the ListView outdoor iself. Okay. Next thing we need is a TableView. I'm going to make this class data source and delegate for the doom view. And we also going to register a cell. So this is just for your active cell phone now, for federal ID. Alright. Now this is going to complain that these, that this class does not conform to these protocols. So let's go ahead and give the conformance. So we have, we can eliminate d debtors. So first we're going to create four don't list, view, photo, list, item, delegate. Okay. Photon list-item delegate. Okay, it's going to have this function. Okay? And what do we want in this function basically on a dispatch queue, main async. And I'm going to reload the detail view. Reloaddata. Okay. So next extension, you I do. Oh, sorry, sorry. Photo ListView. Ui table view. Delegate. Each one. Photo and distribute UI table view data source. For the number of rows. In section, you're going to simply return. We model dot photos.com, okay? So count heads on the cons. So we are going to have done that for cell, for row at index path began to create our cell here. So AMI, the night gets returned. It will be scaled, so all the arrows can go away. Hey, do this. Or don't list view model data. Yeah. Oh, DO list view model. That again, that it's a devastated that we need this one. And we're going to stub back on out. And we're gonna do the same thing. You know, they go, right? So there's gonna be no data. This is UITableViewDelegate within actually put functions when I didn't have selected or we need to return the height. So we do actually have a specific height did run a provide. So it kind of say height for item are hot, hateful or role at index path, and we're going to return a hundred-year. Okay? So our love ourselves. So I'm going to be of height 200. All right, so that's going to, that, okay, so it's going to try to build out. And we should be able to build. Okay, cool. So that's awesome. Now let's go ahead and continue our photo list for you. Okay? And we're going to have an initializer, which is going to call super.net for frame 0. And it's going to call a function setup. You. Okay. All right. Said he is not there, so let's go ahead and create that. And centered view is simply going to add that table view, add subview d little u. And it is also going to call setup constrained a, another function that we're going to create. So stent up strains. Okay, here we are going to be laying out our DOB without layout. So we're going to simply say NSLayoutConstraint. So you can use anchor based constraints and you want to constrain our table view. And on the old side of the view, so you can give us at least a day will be dot leading, hanker dot constrain equal to leading anchor. And I'm going to copy that, paste it. And we're going to use this for trailing and current oil banker and for bottom anchor. Okay, so those are going to be our Lakota constraints. Alright? Now, now what do we need to do is basically set up our cell, because right now we are just set up a UITableViewCell non-self. And that is that it's all right, but that's not going to display our content we learned just play themselves. So let's go ahead and define a custom cell. So I'm gonna create a new file photo cell. Okay? And this photocell is basically going to be a class was to fall. You can import from UIKit photo cell on the UITableViewCell me than 1800. We're going to create a function for own reuse. So when Eleanor reuse happens for the cell, you want to call this function. So it's going to be a closure which is going to be initialized with empty. Okay? This has basically two and get the reviews cell setup. Okay? And I'm going to create our image view. That's going to be our image view. And then we're gonna create our photographer level label. This is where we're going to show his name and his or her name. Always. Remember to set this translate auto resizing mask into constrain to false. If you're using programmatic auto-layout begins the wave your arm layer system that would run into conflict because it'll try to create constraints for you. And you are also creating constraints. So just remember to say that the most common error that you can make any do miss. Send that text color to white. Okay. And then we need photographer stag. But she's going to be pretty same. Var here. I'm going to copy this bag. Label, tag, label. Okay? And this is going to be only little constraint on sides. It's going to be a protein and it's going to provide awesome. Okay, so now we can create a blurred view. The Blur view that's going to stay down the top of the image to show for Darwin first and name and his tags. So you can basically create a private lazy var Blur view. So blur effect, ritual, you. We're gonna enqueue it this style, dark. Let's create a blur view. For this UI. Visual effect. View that takes an affect and effect is basically blurring effect. And this is what we need to urgently before returning, referred, returning this, we need to set translate Auto Layout to false. Otherwise it's going to cause issues. And we're going to return Blur view. Okay? So that's our blurb you. Now we are going to create our initializer for cell and we're going to call super dot in it. And supplied the style and the reuse identifier. Okay? And then we're going to call setup view function. So this is going to be another function that's going to set up this way. You can typically do it like that. Now, we need a required initializer to kind of simply. Like this. And that's OK. We can leave it as fatal because you're not diminish writing anything using storyboard end says actually required. I never you are initializing views using storyboards so we can leave it like that. So if somebody calls it type by mistake, they would know that programming is going to crash because it's not implement it. We're not planning to implement it. Okay. Now, set up, you're going to create lung function and set up, set up constraints. Okay? And let's call this function. Let's create this function as well. Okay, so for the setup view, we are going to basically set up Image View and Blur view. So let's put a foreach on those. And we're going to say V in. And we can simply take the content view and add subview v. So it's basically going to add both of these views into the content view. And then we're gonna do something similar for, for doubt for a label and a choreographer. Labels Dad. And we go say for each. And we're going to add these on blur effect view. So blurred effect has content view. And we're going to add, so bu, the view that we are getting right here are the for each loop. Okay? So that's going to add our views. And then now we're going to set up our constraints. So you're gonna say NS layout, constraint up activate and less setup human huge constraints. You're going to have leading anchor, photo constraints equal to content to you, doc leading. We want this image to be edge to edge. So for the training we're going to do the same thing. Content view dot trading anchor. And for the DOP anchor, we gotta have top and bottom Content Views. So you're going to make the image cover the entire style. Then blurb. Let's add constraints for bad. Blur effect view leading is going to be constraint equal to content view dot leading incur Trailing, it's kinda be constrained to content when you dot trailing anchor. And then for the bottom, bigger say content view dot bottom. And we're gonna give this a height hyphae. I didn't hide constraints. So height anchor constrain equals to constant. And you're going to say, we want 50 of height, okay? For the photographer, label and bag. We're going to have layout constraint. We can then use to or load that data constraints. So we're gonna say Blur view dot leading anchor with constant to write. And it's going to give us a margin. Basically, for the trailing, trailing anchor, we are going to do simplicity. Trailing anchor. And countless constant is going to be negative. Do. Because if you give two, it goes beyond the bounds of the view. And DOB anchor is going to be the photographer and they will stop. Anchor is going to be topping curve for the Blur view with constant 24 for the photographer. Bag. So let's add bag label, tag, label, OK. And DAG labels leading is going to be the same as Blur view leading. Okay? They do. Trailing is going to be similar because he went to anchor them leading and trailing the same. As a photographer label. The difference is going to be top and bottom. So for the top anchor, you're gonna constrain it to photo for direct firm label, dark, bottom. So whenever photo photographer Libo ends at the bottom with two points of margin and for the bottom anchor for the tower bag label is going to be polar views. Bottom, anger with negative du as the constant. Ok. Now, one more Horn. Last thing we need to do in here is prepare for reuse. So prepare for reuse. So we're gonna call super dark. Prepare for the US first so that the day will be cell do whatever the super class needs to do. And you're going to call our Henri yield herself. And we're going to also set image means image to nil. Okay? Alright, so this is our cell that has set up now. So in the, in the next section we're going to have basically setup, wired up this tell to our table view and then start loading the images. So start populating the data. Okay, so cool. 26. Photos App Home View Controller: All right, so let's continue forward. Basically what we need is now we have our cell set up on photocell setup. And let's go to our view controller, or basically the photo List View. And inside that view, we need to actually set the cell. Okay? So first thing, we need to insert out, like, you know, for the register instead of filling disappearing UITableViewCell, we should register our custom cell. So you're gonna say Ford or sell dash itself. Okay, that will give it that type to register for the cell. And next thing we need, It's basically get the row setup. So right here, self or her role at index path. Okay? So the way we can set up row at index path is going to be the first. We're gonna get the cell from re-usable felt till DQ, reusable cell. So this ensures to performance of our people view. And what we can do is we can actually create a static, static, static variable. And instead of using or bears or we don't need to study, actually just create a constraint that we can actually call it for all the instances. So fair lady, here. And we're gonna do the same thing here for cell ID. Okay? And you're going to pass the index path that we have received right here. Alright. Now, we need to cast this cell as photocell because what is DQ reusable cell gives us is a UI table view cell. Okay? Now we're going to return a cell. But if the cell is nil, if there's casting right here, it fails, then we should return something. So you can return a UI table. So this is going to create just an empty cell. Okay? Then next thing we need is a photo. So we're going to get to the view marble and ask it for a foreigner or at index path, index, path, index and index we're gonna receive from index bat dot roll. Okay, now from here on, we just need to set the photographer labeled text. So photo dot, photographer back is go for a tag. Right? Now. These are the label properties that backs properties, but what about the image, right? We haven't, we have the image URL. So photo has under source, it has landscape and portrait image URL, but those are just strings. We don't wanna actually bass strings, but We want to show the photo now, be just ran another photo like that. That is I mean, every download a photo and be display the photo. That's going to work. But it's not going to play really well inside that they view cell because of the reusability aspect and the nature of that people under your rule of can be scrolled up or down. So those images that were being downloaded, the, it'll download at a later time, right? You're gonna run into an issue where you are capable of being reused in, then your image actually shows up because they were just downloaded. So in order to overcome all that, or we need to do is basically we need a, we need some sort of image loader that can maintain in-memory cache. And basically whenever an image is. And a question using URL, we check if the image is present in the memory. If it is, we're going to write down that. Otherwise, we're going to simply make a call and return the image at layer one. And now we also need the ability do cancel the ImageDownloader, Dao Wei weekend manage their state property and we proper property. And we don't unnecessarily download the image when the cell is not being displayed. So for all that, we're going to create an image loader. So I'm going to right-click on networking folder, create a Swift file. You're going to call this image loader. Ok. And we are going to be important for me UI kit. This is going to be a class loader. You're gonna create two private variables. Well, if first one is going to be loaded images, second one is going to be running requests. So the current requests that are running are that are being performed by the system fora image download. Okay? These two values, these two variables we're gonna use to maintain the state of our image loader. So first one is going to be our cash. Second one it's going to be on the running requests that are basically being performed for ImageDownloader. Then we're gonna create a function Lord image from a URL. And you're going to have a completion block when the ImageDownloader done. And while the result, we're going to get UI image in error. Ok. Now this is going to return, this closure call is going to return void. And this function call is going to return a UUID, UUID with one. Value that we're going to use for the cancellation purposes. Okay? Okay. So what we're gonna do is we're going to first check for the loaded image. If for the given URL and image is already present, right? If there's already present, then we're going to call the completion with success. And we're going to supply that image that we just found. And we're gonna return nil for a UID. Okay? If that is not the case, then we're going to create UID. And we're going to create a task datapath with URL we can use. And here we're going to receive three things, the completion, beta, response, and air. And we're going to simply process them. So first thing we're gonna do is gonna call differ for running requests and remove value for key UUID, which mean that whenever this task gets completely, that means that that image has been downloaded, so that operation is no longer running. So you're gonna remove that UUID from the running requests. Ok, so if there's hardly any downloaded, that means the images now in the cache, so we don't need to cancel or anything because they're running requests is something that we're going to use them for family cancellations. Okay? So the next thing we're gonna do is we're going to check if Lead Data and let image from data. Okay? If we get those, then we got I simply call self dot loaded majors and we load or store the image inside occluded image and call completion with success. Supply image return from here. Okay? Next, we're going to check for her. If none, then return. Okay? If we've got some error, right, we want to check if we can catch that error as NSError. Because we need the code if the NSA or corn is equal to U, error cancels. So basically B has already cancelled. Right? Then we don't need to do anything if we have not canceled and there's failure, failure error like we got, then we return that. So we're going to let our color no, it's something else other than the cancellation happening. Okay. And One more thing we need to do is first of all, we need to remember to call past operands you. And we need to store the UUID inside are running request because now that could request is running with this slide. That request for that particular image I'll node is running and we're gonna return UID. That's wrong. Now, how are we going to use it yesterday? Well, we're simply going to create a castle function. And this function is going to take a UUID and it'll simply look for the for the task and cancel it, okay, if it's found in there running requests. Now one more thing. We need to make sure that we remove value for you the ID. That's all right. So this is basically going to call our image, make sure our image gets downloaded appropriately and stored. And if there is any running requests or whose cell has been has been reused, and then we want to actually cancel those. Now the grills part, how are we going to handle that call? That is going to be part where we can configure the cell right here. So what we need to do is we need to set if let URL, if you go to first of all, get the URL from string for Bordeaux, dark, source, dot landscape. So you're going to use landscape our a 40 for the, for the image cell, for the photocell. And then we're gonna get the token crests. You marble dot, lauded. Okay? So if you look at the real model, you can get the photo, right? But there's one more inefficient way to do into our new model, which is to download the image or the access to the image, right? So what we're gonna do is we're going to go to our ViewModel. Before. Don't list. We model and we're going to create an image loader. So instance for major daughter. So image loader, pipe app. And we're gonna initialize it right here. Okay? Now once we have initialized, we can create a function that will load the image. So you're going to simply call load image function, load image. And you can create that with URL. This is going to return a completion. Now, here we're going to call r. Image loader. So image loader, dark lord, image. And we're going to supply the URL. And you're going to receive a completion with the result. And here we're gonna put a switch statement on the result desktop because his art gives us two values, success and failures. So we've got to face success, led image and call completion with image. In case of failure. You gotta print the care and return nil for the completion. Okay? And the token that we get, you get no return that dopamine. Ok. There's one more function that we need where we can perform the cancellation. So again has created Gensler function that'll take a token of type UID. And we're gonna say if let Docker is equals to token, that means there is, token is not nil, in that case call image loader dot cancel token. Okay? So this is basically going to help us and download image from the network and give us a token so we can cancel the tensile the image requests and all that God is now wrapped inside the view model. So all we need to do is called a ViewModel to load image for the URL. And we're going to supply the URL that we just got in it we get an image, right? Because dispatch queue go to the main thread and we're going to simply call cell dark image. V dot is equal to image and it gives you a rendering. What's that image view that appearing on every day in medium P. And is the image view that's by default created for default cell. So that's why we created our our property as imagery. Not so not to override the other imagery Well, okay. Alright. So bad is when our token is assigned her images loading. Now, if during this time our cell is reused, right? Then if you recall, photocell, cause this on reuse, on reuse function, right? Closure carl S gonna call this clerical and the closure call is going to make sure that if there is a token back the received, then we're gonna, on the ViewModel, you're gonna call cancel for that token to make sure that our cell is ready to be reused. Okay? Alright, so with this code, we have our image download. Imagedownloader ready in our self are ready. Okay, so let's go into the Home view controller. And the Home view controller, we are going to create our, we are going to add our ordered list. So we're simply going to create lazy var for the list portal list view. Okay? And we're going to initialize that are returned. View. Remember to translate, set translate out of the saving mask into Constraint ED call defaults. And we also want to assign ourself or this view controller as a delegate for this photo List end delegate, right, so let's create an extension for Home view controller. For door list. I don't delegate. Okay, now this required or creates a function selected photo. So I'm gonna end up photos selected. What we need to do is we need to launch a new control are so large detail bc here. Okay? So if you haven't written that God yet, so we're gonna write it when we, when we have that selection, selection operation ready, we don't have it right now. So b should be okay. Okay. I mean, bin aren't gonna do it right now, but we're going to come back and do it in a bit. Let's call setup. You function, create, setup function. Okay, this is going to basically add sub view for our, for the list. And we're going to call set of constraints. Here. We're just simply gonna set up the layout constraint. So activate. And for the photo lift being simply economic, peace, simply going to add it, do constraint if to all sides. So constraint equals to mu dot, leading and curl. Okay? I'm going to base it four times. And training anchor here. Dow banker and bargain Inca, extra credit so that they wouldn't be as ready. Let's go ahead and try and launch it and see what we got. And there we go. As you can see, our images are loading and landscape. Views of landscape art image are loading. And if you notice our image, our images are loaded when the cell itself loads. So it's not, it's not loading are basically creating that effect of liking. Showing another image till the bang, one of the images being downloaded, so it's learning the correct image into the cell itself. Okay. Alright. So are imaged load Bart is done. Now, let's go ahead and set up our detail basically, so we can tap on the cell and we're going to use Delegate Ben for this has to basically, what's going to happen is your list. New is going to have basically self election. And this is going to propagate that event using delegate protocol, delegation, baton. And then our ViewController is gonna receive that Carl, that delegate call. And it's gonna basically propagate that to launch the ViewController detail view controller. Okay, so in the next section, doesn't look. 27. Photos App Infinite Loading and Details View Controller: Alright, so let's go to our folder list view. So we are already here for a ListView, right? And in the foreign ListView, if you scroll down to where our view delegate bite, they will view delegate is. Okay, well, we need to do is we need to have the ability for the user to select rows, right? So we're gonna say did select row at index path. And whenever the user selects a rule, we can get the photo for that index path. So you gotta say getFollows at IndexPath, dark roar. All right, and we're going to call the delegate for selected photo like that. Okay? So we're gonna simply propagate that. To select it will delegate and supply the photo. Now that for loop, it's going to be received by the, by the ViewController that's implementing or the view that the class does say implementing its delegate to ingest this view controller right here. So that's actually how you gonna propagate this select event. Do your view controller. Okay, now here we need to create basically a view controller so we can launch that. So I'm going to create a new file. And we're going to create Detail View Controller. Import UIKit. Do you do in your controller, j's going to inherit from UIViewController. Ok. Now this UIV controller is gonna need viewDidLoad. I'm gonna call sumproduct viewDidLoad. Alright. And a center, your dark background color to be white. Have all. Okay? Because when you view controllers career programmatically, it doesn't have any color, so it, by default, it's sister, MD collar, like clerical or basically now this view controller is going to need a photo. So you're gonna create a property called photo. Okay? And then we're going to need, need a image and image view every going to display the image. So you mentioned you UI image view. Right? And don't forget to a transect. Translate our layout. Translate our resizing mask into constraint to false, and then b dot content. Or it's going to be. Scale, aspect fill. Ok. We're also going to need the close button. So although user can dismiss and by swiping down, it's better to provide a close button in case something happens. It's a good practice actually to provide a way out from your view. Even though there is a gesture that exists. To begin to create a UI button. For that. You can then set title for the button with x and the state is going to be normal. Set title color to be white for normal state. And we also going to add a delegate of self with a selector. Now, selector is an object of z function, so we're going to decorate with obj C. So yeah, at sea, right? And this is basically simply going to be up like, you know, a function that can be modeled using this electrode. So I'm gonna say did that close button. And we're going to dismiss any major true completion nil. And if we're going to call this did tap button for event that jump inside. Okay. And we're going to return our view which is going to be closed, but okay, now, next thing we need to do is we need to add these two. So we're gonna say v dot add subview, Image View, and new dot adds up you close button. Okay? And then we can create our layout. So NS, layout, constraint dark, activate. And here you are going to first constrain our close button. So trailing, anchor dot constrain. Do you dark trailing incur and constrain it from negative 16 from the, from the trailing side. Close button dot top anchor is going to be constrained to u dot top anchor with 16 points. So we have, we have disorder, bu, we haven't reached here almost here. So we can define Close buttons, dimensions for width and height. So close. But dark, width, anchor. Now to constrain equals to constant and say it's going to be 40 points. Quote button dot height, anchor, doctrines strain equal to constant for me. Okay, so that's our close button. Now, our image view is going to be ImageView dark leading constraint equal to. And we're gonna constrain this to all sides of the view. So if you simply gonna say bu dot leading, need desks or we can go back and I'm going to copy and paste three more times. 1 fourth trailing darpa anchor, martyr, Mancur, exome. Okay. Now what we're gonna do is we're gonna basically, when we received the image, we want to download the image, right? So we're gonna say if let URL. So if Bea can get the, construct the URL from string and string, we get from photo dot source, dark portrait. Now this time we're going to use portrait, our photo portrayed version of photo. Okay. And we're gonna say we don't care about the cancellation because when we're loading this image, view is going to be launched, right? So it's going to start the, start the image loading. So we can simply say image loader dot load image for URL. And for the completion, we're going to simply say that result in. So each result, and we get the result. And we don't simply say Success. Let image to begin to emit here. And we're gonna go once again, the image always downloads and whenever like you know, a URL session it's called, it's called on a different thread. So you wanna make sure whenever you are updating your UI, that you are going back to the main thread before you update your UI. So that's why we are doing here. We are going to dispatch queued up mean are distinct. So we can go to the main queue and then we can set the image center image for our image view. If it gets any error, we're going to print the error. And that should do it. Okay? So they shouldn't basically download our image, set our image and federal Reagan Torah. Now we go back to our home view controller. That's where we are actually going to launch this. So like selected for all our this is called, we're going to set the ViewController or create the object for detailed view controller going to set the photo to the photo that's being supplied to us by the delegate right here. And then we're going to simply call Present. And you're gonna present view controller animated shrew. With the completion has now. Okay, so let's go ahead and try to match it. And as you can see, our selection is working in our close button networking. If you notice, they dismiss, swipe to dismiss it also working and we are loading an image, a portrait, virgin portrait version of the image for the view. Right? Now under the park where we want to display it, keep, keep displaying, basically keep the infinite scroll. That concept is that core piece of code is very simple. So if you notice right now if we go reach to the end, there's no more images. So, right images and here. But if you want to have liking or Lord more image as the user is scrolling down that piece of functionality we need to add so that, that is a simple technique. You can implement. A delegate call. Four will display cell, so we'll display. So cell is called cell though. All right. Let's called this play. We'll see, okay, well Display South right there. Okay. So what we'll do is we want to check if the indexPath dark roar, right? If it has reached ViewModel dot count minus ten. So basically whatever the ViewModel compares, if it has reached ten minus of that. So like, you know, we only have ten more images left to display for the user. Right? Then you want to call the ViewModel to art. Lord photos. Again. Now you model dot load photo of what it's gonna do is it's basically going to increment the current page, page number, right? And it's going to call our photo feed with that page numbers. So you have the page number one is going to increment and make the page number two and get 20 more images from the API. And then we're going to basically loaded low-dose images populate our ViewModel. And as the user is scrolling our images, I'm gonna load. So let's go ahead and try this out if it is working. So if you notice, we are scrolling, scrolling. And there we go. Here. More images loaded. Keep scrolling. More images loading. And if we keep going down, it's going to basically load more and more fringes. Okay? So how, how easy it is to basically create infinite loading for your table view. Okay? Alright, so with that, we have reach to the end of this, end of this series. So I hope you enjoyed it. You learned why. Basically learned how to create an app that is completely created programmatically with the best ways to basically separate out your features. So now you have like you know, for a ListView and your home, you can do it if you look at like you know, it has just a few things. Now, for the challenge, you have do challenger basically first challenges, create a view model in simplified this view controller itself. So see if he can basically extract out all the CY related cord from this detail view controller and put it in a separate view, just like we did for the Home view controller, we separated out inside a photo ListView. So try and do that. Test first challenge. The second challenge is, if you remember, in our endpoint, we had 2n points. We had a curated list, and we had a we had a search list, right? For the enumeration. And I guess it was the end point or the end point, or maybe pixel coordinate at that photo, feet, marbles inside the models we follow feet. Okay, yeah, Butterfield had such bad category and curate and now we have use, we have used curated worship to the Lord, display our image. Now your challenge is to basically create a segmented control here. And inside the Segmented Control, you'd have two segments. One for a curated, one for search by category. And curated it's going to be automatically selected such by categories. When you tab, you can type a category or just user category if you want a hard-coded. And then basically let you reser, explore images based on that category. Ok? So those are basically the challenges that you have to take for yourself implementation. And it's going to be similar to this. So hopefully it's going to go smoked. Okay. Alright, so thanks again for watching. I really appreciate everything and I really appreciate you get support. Alright. See you later.