Build Full iOS Photo Browser App in Swift Programmatically: Xcode 12, Swift 5.3

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

IDK if you can do anything about this now, but I had the volume up full blast and I wasn't able to hear you.

One other thing is that you should have the source project linked on GitHub. Most people don't like to type during a tutorial, it's hard to keep up and type at the same time and you have to see the screen, what file is where, etc... Simply posting your project file to GitHub makes it so that they don't have to type it all in.

Thanks for posting, I don't do SwiftUI yet, but I'll watch it later. I'm waiting for Apple to do more work on SwiftUI before I dive in.

👍︎︎ 3 👤︎︎ u/KarlJay001 📅︎︎ Dec 28 2020 🗫︎ replies

Great. Will give it a watch later. Thanks for sharing.

👍︎︎ 1 👤︎︎ u/Cornflakes1009 📅︎︎ Dec 28 2020 🗫︎ replies
Captions
hello everyone hope you all are doing great and welcome to this new course on photos app where we are going to be creating this photos app using api provided by pixels so pixels.com is a website uh that gives you access to free photos uh using an api well they also have a free uh videos as well and basically uh in this website uh your photographers go and upload their creation and uh they actually provide you an api that you can use to download that data or display that data in your app or whatever you want to do with it okay and they're free to use um so you can basically check out pixels.com right here at pixels.com and you can see there are like a whole bunch of photos and as you can see like you know their videos and everything as well they have a very well written api and uh this api once again gives us access to all the data that there is okay so uh the good thing about pixel is it gives you enough amount of data that actually works good for mobile use cases because uh it has a source uh for the api that actually gives you various range and size of images according to the need that you may have right so that's about the api itself that we're going to be using to develop this app uh let's take a look at the app itself so basically we're going to be developing this app using storyboard and uh storyboard by storyboard i mean the not swift ui is the storyboard when you're select when you're like you know creating your project you choose swift ui for the user interface or storyboard so you're gonna be choosing storyboard in that case uh so we can use ui kit okay and uh the code itself is gonna be a complete programmatic layout so there's not gonna be any zip file or nip file or storyboards that have been used inside this project it's going to be completely programmatic and so you're going to be learning about that 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 um we are gonna display uh images downloaded from pixels api um on the uh on the on our app in a table view okay we're gonna display who the who the photographer is and their tag or handle okay and when you tap on the uh photo itself uh you can see a excuse me a portrait uh view of their photo and uh they're gonna be displaying a landscape uh image um or landscape photo so that's where this api is gonna be uh it's gonna come handy uh you have portrait and landscape both of them available as a source for the url so api itself gives you access to those two okay so we're going to be using that uh next thing you're going to be uh you're going to notice basically you're going to develop is going to be infinite loading so um if they if we keep scrolling uh the new new images are gonna load at the bottom and our users can keep scrolling to explore more images all right so this on itself is a rather complex app and uh basically uh there are some learning objectives uh first of all the entire app is written programmatically so there is no use of uh ui or dragon drag and drop based uh ui construction so there's no storyboard zip or nib so you actually get to learn how to create programmatic layout in swift uh we are also gonna be creating abstract networking layer which basically gives you access to a generic based networking layer that you can create a generic solution that can be basically used in any of your apps so you can literally take those files and drop it into another project and start using those and it will simplify your networking layer and it's efficiently managed decodable and everything is generic based so you wouldn't have to code over and over your uh api client okay so how we're gonna we're gonna see how we can how we're gonna basically develop that and um we're gonna use endpoint management using enum so we're going to be using enum not for just for switch case and stuff we're going to be using for endpoint management and we're going to take a protocol oriented approach to basically create protocols and we're going to see how we can extend those protocols not only within structs but within enums as well okay we're going to be using swift generic so we can learn about swift generics so that's going to be your entire networking part api part then uh you're also going to be learning mbvm design pattern so basically how model v view model design pattern works and how you can actually leverage mvvm to create lean view controllers okay so your 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 they only perform enough tasks which is the communication between model and the view all right so that's gonna be another learning objective for this course uh 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 table view and i cannot stress enough like you know how important it is for you to understand how to load images in tv because if you have worked with images in table we sell you know how hard it is to basically uh display an image inside a cell and whenever that cell reuse happens that flickering or loading of wrong images and stuff like that that all happens within people view and it's quite a challenge so we're going to be learning how to develop an efficient way of loading images in table view we're going to be loading all the images from network so you're going to learn how to load network images you're gonna learn how to asynchronously load images and cache them okay you're gonna learn how to handle downloads image downloads and cancellations if the row is no longer visible so you can prepare the cell for reuse within table view okay you're going to be learning how you can leverage the infinite loading of the cell so whenever user scrolls at a certain point you can load more content at the bottom so your user never runs out of content right so that's going to be another thing that you're going to be learning we're going to be using delegate pattern as well in this course to propagate events and we're going to be separating out the view from view controller that way we can manage views state separately and view controllers state separately okay so there's a lot in this course that's jam-packed and we are going to be creating a production quality app so basically you're going to be learning how to create a production ready app and these concepts that you're gonna learn you can apply this concept in your next project and you sure will see that a lot of benefit and reuse comes with those things all right so i hope you're excited to uh join me uh 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 i'll see you at the next video hello and welcome back and uh in this video we're gonna start our project so what i've done is uh i created an empty uh project and while um creating the project so let me show you uh if you go file new project and you choose app when you click next all right you click next uh this is where you're gonna enter your product name uh your team id uh your organization name um and then uh here uh this is the place i was talking about so interface uh ui kit based interface apple still calls it storyboard so mind it like you know you're not gonna be coding anything in the story in storyboard files but still called storyboard okay so we're gonna be choosing storyboard okay and uh not swift ui in the life cycle is going to be uikit app delegate lifecycle so when you're creating the project make sure you select this one okay um so once you have created uh 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 delete it okay because we're going to be launching this view controller programmatically all right so that was the first thing second thing you can you need to excuse me second thing you need to do is uh go to info.plist and in the info.plist you will see application scene manifest okay so expand that and once you expand that you're going to see scene configuration expand that too okay application session roll expand that you'll see item zero in there and as soon as you expand that one you will see storyboard name so we need to remove this from here as well okay and same so uh so basically this ensures that our app is not gonna try to load uh main.storyboard but it will try are programmatic way okay now last thing you need to do is go to your project settings general main interface just room just select main and remove and hit enter okay save that and that's about it now how would we go ahead and launch the uh view controller that we want to have as an entry point so i'll show you right here but we're going to delete the default view controller and we're going to create a new view controller home view controller so we know which view controller you want to launch okay so uh first thing what what 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 scenes on the ios side there is only one scene that you see but if you use ipad or mac os then scenes can be uh replicated so you can have multiple scenes for an app okay so you're gonna go to this section uh scene will connect to session okay here uh you'll see this guard let underscore scene window scene so for this underscore we're simply gonna say this is called window scene all right and then we're gonna create view controller uh variable and we're gonna assign view controller into this so we're gonna initialize a view controller and this view controller is just view controller class right here okay so we're gonna initialize this view controller and assign an object so we're gonna create viewcontrollers object okay once we have created this object we're gonna use uh window okay and we're gonna create our window so we're gonna say ui window from scene so windows scene and we're gonna say window.rootviewcontroller is equal to viewcontroller okay now this is this last step is most important uh to make key make this window as key window and make it visible okay so in order to see if we have everything working properly or not we gonna change the background color for our view to red right 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 uh for the initial launch it may take a bit and there you go you have your red view controller launching that means our programmatic initialization is successful okay so that is uh done so let's go ahead and remove that that color uh red color and as soon as you create you can totally gonna notice that your view controller is created with background color as black okay so we're gonna simply set the background color to white all right okay so we are all right we are done with this one so what we're going to do next is uh i'm going to create a few folders so let's go ahead and start creating some folders so we're gonna need folder for view controllers so view controllers okay we're gonna need um so just select right click and select new group then i need a folder for views okay and i need folder for models and uh then i need for view models and one for networking all right okay so we're gonna remove this so delete okay we're gonna create a new um folder so now for these files uh these are support files so what i'm gonna do is i'm gonna select these and set them in a new group without folder so this is going to be the virtual folder so i'm going to call this support files okay so that didn't take any effect so i'm gonna manually move these okay all right so at the end this is what you should see if you try to build your app you're gonna see build fails because we have that scene which has this v controller missing so we can fix that now so let's go ahead and right click on your view controller add a new file and you're gonna add a new swift file um you can add a search file or you can add a coconut cocoa touch class and coconut class takes a base view controller a base class that you can actually uh create your object from so let's create quick attention in this case and i'll show you the other case uh in uh next class creation so you're gonna call this home view controller and we're gonna simply save this so we're gonna create okay so our file is created okay now if you notice uh there are a few things that new controller needs so view controller inherits from base class ui view controller and it has muted load okay so next time when you're creating a file you can simply choose a search file and write this out yourself all right so go to your scene delegate and change this to home view controller like so and come back here and set up background color is equal to white okay go ahead and build it again and you should be able to launch the app successfully okay all right so now we are able to launch this um this app programmatically so that's good uh next thing we're gonna work on is going to be the uh models uh layer so we're going to create models for our photo feed and for that we're going to check out the api all right so what we're going to do in this uh section is basically we are uh going to sign up for pixels so i've already signed up so you simply go to pixels.com so p-e-x-e-l-s-com and uh go ahead and click join to basically join it's a free registration all you need is your email address and then you'll be able to create your account and uh once you have your uh account created uh there's gonna be a confirmation email as soon as you confirm your email you'll get an api key okay so once you get the api key um you will go to documentation section it will show you like you know it's you get the api key that documentation is uh listed there okay so once you have the documentation listed uh you land on this screen when you click on that link okay and uh this link has like you know whole bunch of things there is an authorization so i'll talk to you about authorization in a uh in the in the video itself how to do that but authorization essentially the way it um the way it goes so let me show you okay so authorization is an authorization object uh by the way uh this is my uh key so please don't use it please register because it's absolutely free and go ahead and sign up and get yourself an api key okay um but once you have registered and got the authorization authorization this app this api's 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 um request stuff from the api so you'll be able to start getting response uh you're not gonna get 401 or unauthorized uh error okay so uh make sure to get your api key right then we're gonna look at photos objects so there is gonna be the photo object that actually tells you about the photo itself now what are the things that this api provides right there's only going to be a few things that we're going to be interested in for example we are going to be interested in id uh we are not going to be interested in with our height or at least in this case i will not be but if you are interested please feel free to do that there is a url so in case if you want to provide a url back to pixels then you can use this url okay so you can have a functionality where user taps on the photo and they can check out this photo in a web browser or something you can have that too okay so that's why url is there then you have the photographer who took this photo and the photographer's url so photographer itself uh their profile so you can have that too in your in your uh app okay so for our case we're gonna be needing id photographer just uh for the name and then we're gonna need the url but we're gonna only extract the part of after at so this entire section we're gonna take it out and create a add symbol like our tag for them so we're gonna call this photographer tag okay so we're gonna see how we can do that and then um we might need uh basically uh yeah we're gonna definitely need photo size so basically size is the source and uh this is another object that has portrait and landscape valley so we're going to create another class which is going to contain these two so we can actually create this whole thing quotable okay if you notice this all response all this comes in um basically um with a feed result okay so let me see okay so let's look at the curating part so we're gonna be uh so i'm gonna show you how you can use enum to provide different values so if you want to search for photos you can have this section if you want curated photos you can have the section we will work on curated photos uh in this uh example and there's gonna be a challenge so for you um basically you're gonna be working on a part where you're gonna provide search for photos another view controller that can be launched and user can search for photos okay so we're gonna be providing both endpoints now if you look at curated photos and uh basically uh yeah curated photos or search for photos both of them have similar json response if you look at this so uh let's look at curators 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 for pages how many results you want to see on the page and then you have photos and the photos is an array which actually lists out in individual photo object that you just saw okay the photo object this one um so in our api response we need to code our model in such a way where it can take all these values right for search for photos the only additional thing is total result total result actually gives you how many results are there and then you have page per page and once again photos so this tells me that there's only going to be one photo feed result for both of the apis so we're going to create one of that okay so with that let's go ahead and jump into xcode and we can create this api so i'm gonna set this documentation aside and uh so now we're gonna create our model so right click on your models folder and create a photo feed result so here's the file called this photo feed result okay and uh foundation is okay about foundation gonna create a struct photo photo feed result this is gonna be codable and we're gonna have those uh tags or those fields that we saw in our documentation so once again pulling up the documentation these fields we're gonna type them ss okay so we're gonna type them as is that's gonna give us stability or give codable ability to decode those all right okay so total results and page okay so we are 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 n to create a new file and i'm going to call this photo okay and this is going to be our photo object and here we're going to create a struct again called photo portable okay now if you build once you have the photo created your build is gonna succeed and uh this complaint is gone that this object doesn't take this because now it does all right so back to photo we're gonna create id photographer you're going to create a computed property out of photographers url and uh we're gonna basically simply return photographer url dot replacing occurrences off so we're gonna replace occurrences of string with something so we [Music] so let me paste the code and then we're going to talk about it so go back to the documentation and i'll show you all right so when you get your um response like your photo object when you get a photo object uh there you go okay your uh photographer url has add sign at the end right so we need to take this entire string and replace it with space or empty basically no space uh what this is going to do is gonna basically just get this part of the uh of the photographer's name okay so if you are extending this app to basically provide photographers um photographers profile then what you can do is you can create this you can keep this as a base url and then append the tag to basically generate uh the url for the photographer okay that's how you can do it all right so um the remaining everything else is uh yeah it's pretty self-explanatory so i'm not gonna go into detail of that oh so let's go ahead and set aside the documentation once again and go back okay uh what we're gonna need is basically the source which has the photos uh size of the photo so i'm gonna call this photo size okay and this object is not created so let's go ahead and create that as well okay so photo size is gonna have landscape and portrait uh landscape is the one that we're gonna use to display in the table uh view uh cell so we're gonna display a photo in landscape and they will be cell and uh when we when user taps on a photo then we're gonna launch is its portrait version okay so that is something that can do go ahead and build and you should be able to build now okay so uh now our models are ready actually so we have photos we have photo feed uh that actually gives us the entire response we have photo and we have photo size so um so all of these are more models uh related to uh the response itself now how about the response itself like the response that you're gonna get how are you gonna handle how you're gonna handle the base url how you're going to handle the url construction and stuff like that so that is going to be next we're going to create one more model but that model is going to be related to networking code so let's go ahead and and look at the uh networking part and then we're gonna create some protocols and we're gonna create one additional protocol to handle the endpoint management using enum okay all right so in this section we're gonna see uh how to manage our networking part so uh right click on your networking and uh basically launch your new template new file template wizard and we're gonna select swift file one more time hit enter and we're gonna name this file endpoint okay so this endpoint is going to be a protocol that is going to provide base url path for the for the api and any query that you might have it'll also have an api key uh so it this is where we're gonna add the auth header uh create url uh basically for the api and creator request okay so let's go ahead and look at that so we're gonna first create a protocol we're gonna call this endpoint and this protocol endpoint is going to have a base gettable property path query okay now we're gonna extend this protocol with extension and extension is a way to add more functionality to your protocol or provide default implementation we're gonna add a bit more functionality into this so we're going to create an os header now if you know about protocol you know that um protocols don't allow any kind of definitions within them right vertical body itself but if you need to have a definition or default implementation you should always include it in your extension and you can only include an indian extension at this point so um surf restricts you to provide any kind of definition within the protocol definitely protocol declaration itself but you can use the extension to provide default implementation for those these implementations are still overrideable but they give you a default way where your user does not have to implement them if they don't need to okay with that first variable first property that we're gonna need is gonna be auth header okay so us header is basically the api key the um the api key that is given to us by uh pixels api so we can need that so i'm going to create a new file here called api and this file is going to have the api key okay and you're gonna have static lat key and your api key is gonna go there now i'm gonna put my api key and gonna jump back into the endpoint so you go ahead and grab your api key populated in there and i'll see you um in endpoint class endpoint struct once again okay all right so hopefully you were able to find the api key and you were able to put it so when we have put the api key we can simply return for the auth error the api dot key like that okay now here uh we are also going to create a url components url components okay and this is basically going to help us construct the url all right for the base url we're simply going to say take the base that has been declared inside the endpoint if nothing is provided just create empty url component and then you can say component.path is equal to path and component start query is equal to query and then return the component itself okay next we're going to create a request well there are components we can construct url from your little component if url is not there i'm just going to type some dummy url so all right you can put your fallback url here um and i say for the request i'm gonna create url request object passing url and for the request we are going to set you're gonna force unwrap this one because this one is gonna generate optional so we know that we are passing this string so we can actually force unwrap that one and uh i'm just gonna say result dot set value and this is we're gonna where we're gonna set the auth header so we're gonna say auth header for field authorization so it's going to be the authorization field request header and we're going to return this request okay all right so this is our end point now uh like you mentioned uh in the last section that we're gonna need one more um model and this model is gonna be an enum this this model is going to provide us a way to basically choose between search by category api or curated and it's also going to provide endpoint the base url the path in the query okay so let's go ahead and create a new file in the model i'm going to call this one photo feed okay and we're gonna create an enum here and we're gonna use enum to basically provide us uh provide us this functionality of choosing between two categories so there's gonna be a case uh search by category okay this uh it's gonna take two associated values that's gonna be category of type string and per page uh int so basically um when you're 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 page int per page okay so these two associated values it's gonna it's gonna provide uh now we're gonna create an extension on photo feed itself and this is going to extend that protocol now protocols can be extended by our protocols definition can be provided by enums as well okay so now your compiler is going to say type photo feed does not conform to protocol endpoint and we do want pick to conform to protocol so we can simply say okay fill in the blanks for me and there you go you have your base uh url string created so we're gonna simply uh return our base url for pixels so base url for pixels is api.pixels.com 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 okay and there are going to be two patterns to follow uh there's gonna be one uh which is search by category so i don't need any of these um for this case i'm simply gonna return because i'm only creating the endpoint and i'll leave so right now it's only path so you don't need the other associated value parameters by the way uh you're gonna need those in the in the query part okay curated once again take these things out and return curated 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 it takes http api.pixels.com curated for a page right is equal to one so one record per page now you can change that he can also pass um so the request okay so you can pass for the parameter you can pass per page so default is 15 if you don't pass it uh we're gonna pass it and the page number the the number of page you are requesting so we're gonna basically use this to increment you know increment like you know to get like second page third page and stuff like that so we're gonna pass this one as well right so go back to our xcode and for the query we're gonna once again put a switch statement on self search by category now here we are interested in so the associated values so i'm going to type for um search by category so category that you're gonna select and per page okay and this is going to return a query is equal to category and per page is equal to per page okay so this is what we was gonna return for search by category for cube rated it's gonna once again take so ctrl e and we're gonna remove these and simply say let current page let per page and return so i'm going to paste it paste in this code return page is equal to current page and per page is equal to per page okay so that is our query uh which is gonna be um so when we request this enum dot uh query it's gonna for a curated case it's gonna give us the query api dot with base and paths and everything um like you know with the page numbers that we have we are requesting okay so that is the next part where we can actually talk about how are we gonna get the end point working so it can provide us the entire url and you're gonna see basically um well i mean fetching the response if you look at your endpoint right here in your url component you're already using these components so you're going to say base path and query so sorry i take the back take take it back you already uh so this end point right here is what we're gonna use to call um and uh photo feed is gonna provide us all all this information so whenever we're gonna say photo free dot photo 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 and for the query because that url is being constructed um right here the request is being constructed right here so uh in order to construct this year request you can uh have a url component your url component already requests the base which is uh for for your photo feed case it's gonna provide the pixels uh for the path it's gonna provide uh we're gonna be interested in curated but whichever path you have passed it's gonna provide that query whichever query path you provide or query you have provide curated or search by category it's gonna provide that so you're gonna get all that information right there okay all right so this is setting up our endpoint all right so let's go ahead and and look into our other networking related components all right so in this section we're going to create our generic networking layer that we were talking about and um next a few files that we're going to create these files you can literally take them and drop it into your another project and see and basically work with networking so let's go ahead and take a look at that so i'm going to create under networking section i'm going to 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 gonna have two generic types t and u and we're gonna say where u is error so we're gonna given give the type for you that's error then we're gonna say in case of success we're gonna pass t and in case of failure we're gonna pass you okay it's your generic result object that we have created here all right now we're gonna use this uh inside our other classes that we're gonna other strokes that you can create okay so uh let's create a new file and we're gonna call this one api error so basically these are the errors uh error cases um that you may encounter like or your api may encounter uh during these uh uh networking sessions so we're gonna create an email for that to capture them properly so api error and we can have a request failed first one invalid data response unsuccessful these are uh the error cases the api error cases that we can track and we're going to create a localized description property that's going to provide a localized description a string based description for these errors right so we're gonna simply return what this error is so in our case it's simply gonna say just what the error reads okay so this localized description is providing a localized description for all the error cases uh that um that will be generated okay we're gonna create another class or another start and this one is going to be api client now api client is going to be a protocol i mean we're going to create a new file we're going to provide the api uh client protocol okay so let's go ahead and create api client right and this protocol is going to be a generic type so protocol api client okay it's going to have session which is going to be url session get a good property and it's going to have a function called fetch okay and this is going to be uh taking a type decodable so it's going to be a generic type decodable any decodable type will do we cannot expect request parameter to be passed in so url request you're gonna have a a closure basically for decoding itself so i'm gonna say this is going to give us a decodable object and then we're going to have a completion and this completion is going to give us the results all right so this is your api client protocol let's go ahead and check it out um oh yeah there we go okay if we build everything just should succeed okay now we're going to provide an extension for api client and we're going to create first we're going to create a type alias for our task completion headlight so this is going to be decodable api error just gonna return white all right now we're gonna create a private function uh decoding task which is gonna take generic type d of type decodable with request your request decoding type t dot type now the steeler type is the decoding type because your decodable object takes the type itself right so with t dot type we're gonna get the class or the struct the decodable type name itself okay all right with the completion escaping json task completion handler okay this is going to return url session task to us okay now we're gonna create a task session dot data task all right and we're gonna generate a data task from with request so request that have been passed in to us right here okay and um we will use the completion that gives us access to data response and error okay now we're gonna check first thing is uh if we can cast the response into http url response or not so http response and here uh if we can't then we're gonna pass the competition back with nil request field and we're gonna return from here now if the sgp response status code is 200 everything is okay then we're gonna try to get data and we're going to wrap this data into do that so generic model that you're going to get from json decoding so we can send json to dcode and here we're gonna say decoding type remember decoding type is the type that's been provided to us with the t we can whatever t is uh we're gonna get its type with the decoding type okay and this is gonna be from data okay for the completion we're gonna pass generic model back i'm gonna catch if there's anything and i'm gonna pass completion with nil and say json conversion failed okay for the else case oops we should provide put equal sign okay for the else case gonna simply provide a completion with invalid data right and for the last else case where http response is not 200 we're gonna provide a completion with no response unsuccessful okay at the end we're gonna return task okay so this is a private function that's going to be used inside our fetch function so let's provide a default definition for fetch itself all right so i'm going to take this method signature right here of typing the whole thing there we go and uh remember we talked about like you know how protocols can have default definition this is what we interpret we are providing we are saying like you know patch has api client has this fetch function which has 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 that helper function we're going to pass our request and the type to ourself okay and this is going to give us a json decoded or error right so we're gonna simply say dispatch q dot main dot async okay and json so let's get the json first if there's any issue um if there's error and we got the error then we can simply return that in the completion otherwise we are going to return but well if error object is not nailed and then we can then gonna return the error update itself otherwise we're gonna return result dot failure invalid data because we could not get the data right and we're gonna have a return right here okay now we're gonna say if let value that means can we decode the json that we got right can we if we can decode that then we're gonna provide that in the completion inside success otherwise we're gonna simply call completion failure json parsing failed and once again right here we're gonna say task dot resume so this time we're gonna resume our session task okay um so what once again this is going to do is um basically uh we are going to get a decodable uh object so this decode task decoding task helper is gonna help us basically uh first of all uh make the request so we are making the ur request here uh that means we are calling the api right we are getting the response and we are basically finding if the response is okay if response is okay then we're gonna create a generic model out of that okay and um that model is gonna basically decode the type for us according to the type defined okay and that decoding task is basically called inside our fetch function so we've just broken down this url session task into two different functions right so this is gonna basically call the decoding task yeah and uh the decoding if you notice um the decoding type it's a completion right here this guy right here it actually gives you access to the json if the value is there that that it gets that from the from the closure block and it assigns that value so we can actually pass that inside the completion so what you're gonna get is the model itself um for your api call right so you're gonna make the api call and you're gonna get your model populated okay now these three files result api error and api client are generic so basically you can take them and drop it into another project and start using as your networking error now how can you use this that's the topic for the next section all right so let's talk about how to use this api client okay so what we're going to do is that we are going to create a new file and we're going to call this file pixel pixels client and once again import from foundation is okay we're gonna create a let's create a final class pixels client api client okay you're gonna create a session url session and you can have initializer initializer is gonna take a config your session configuration and we're going to say self.session is equal to and we're going to construct our url session based on the configuration that is provided you're gonna have a convenience in it as well which is simply going to call self.init with config default so with the default session if someone calls that initializes this one then we're gonna create a default uh session configuration and we're going to create url session using default configuration otherwise they can also provide the session configuration okay now we're going to create a function that is going to get photos for us so we're gonna create function get photos okay and remember api client already has implementation for all of its uh functions so the only function that it needs is uh if you go back it's it only needs fetch function uh session is something that we're gonna have to initialize so we are initializing that uh fetch function has a default implementation so we don't need to worry about providing a default implementation unless you think that you need to override this okay um so we're gonna create a function get photos and we're gonna get this from photo feed so i'm going to say photo feed type and type is going to be photo feed once again the reminder for the reminder photo feed is the enum that actually provides us two cases uh search by category and curated photos okay so we are expecting that and we have a completion result photo feed result and api enter okay this guy is gonna call fetch function and uh we're gonna create out of the photo feed we're gonna create a request so this is where we were talking about how we are tying everything back together inside the end point right so when you create the end point protocol you create this endpoint has um so when you create this endpoint protocol or extend this endpoint protocol for example inside your photo feed right at that time you're providing base path and query these three definitions your endpoint itself has this url component and request now url component uses these base paths and 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 are saying photo feed type right dot request so it's calling this request it's it's collecting all the data everything that we need for to to make this request so it's collecting the url with paste path inquiry values and then it's also uh collecting the aus header uh so it's setting the author and returning the request itself that we ultimately pass into our api client okay now we have passed that right and uh we got json back for our decoding so we get the json into our recording and this is going to be auto feed result type right so we're gonna simply say card let photo feed result so this json uh yeah photo result and we're gonna cast this json and try to cast this json into that otherwise we're gonna return no if the cache is successful then we're gonna return photo feed result this guy right here and we're gonna call our completion okay all right so this completion is gonna basically have your photo feed result okay and if there's an error we're gonna get the error right okay so get photos is gonna call the uh whichever type of feed that we are providing and that's how you can use your api client okay so once again all we are doing is passing the uh getting our feed type and getting the request out of that we get the json and decode it so we get the decoded json we try to pass it okay we when we pass it uh we get the completion we uh pass that completion player back to the caller of get photos okay so that's how we can use the api client right so now um we are actually ready to start looping this into um or let's put this into a uh view model and uh then you can see how to use this or how to call pixel client or get photos to get the photos out of pixel api all right so let's go ahead and create our view model so we're gonna create just uh one model for list so i'm just gonna right click on the view models folder and select a search file and we're gonna call this one auto list view model okay now we are going to import from ui kit this time and uh we're going to create a final class photo list remodel okay now this photolist view model is uh going to have a photos uh variable which is gonna contain all the photos so it's gonna be an array of photo okay we also need some way for our uh view controller to know when photos are loaded okay so we're gonna use delegate pattern for that so we're gonna simply create a protocol and we're gonna create it uh we're gonna name it photo list view model delegate and the function uh that's gonna be there the only function is gonna be there is gonna be photos loaded okay and we're gonna create a weak variable delegate optional okay and uh excuse me now we're gonna create our our client so pixels client all right and this pixel slide is basically going to download these uh uh photos from the api okay let's create another variable called current page okay and during the initialization or for the initializer of this view model um we are going to initialize our pixel client like so okay and we also gonna call a function called load photos now this load photos is gonna be an internal function or actually we're gonna okay yeah let's not let's leave it open for any for the view controller to call so this load uh photos function uh is basically going to utilize our pixel client to get the photos okay so let's go ahead and first thing first uh because our current page is zero we're gonna basically increment in the current page so whenever we call this load function it's gonna increment the page so we are actually assuming that that user has scrolled to a position or it's a first-time request so we want to actually increment the page and then make the call to the client so we send like you know the page number as one two three and so on okay so we have incremented the current page now we're gonna create our feed this is gonna be photo feed we're gonna use curated version of photo feed current page we're going to supply the current page value and per page number of results we're going to say we want 20 so we want 20 um photo uh 20 photo results from our api then we're going to say take a our pixel client object that we have created and call get photos here from feed okay this gives this gives us a results so we're gonna take a result and we also gonna capture uh self okay first thing we're going to do is we're going to try to get self all right then we're gonna switch on result and we have two cases we have success which gives us the feed the photo feed result so fortified result yeah and uh then we say card a let photo resolved from photo feed result otherwise return so you want to make sure that we get photo feed how that photos resolved okay and uh then we're gonna call strong self and set photos dot append so we're gonna append uh and we wanna append items so we're gonna use the overload that takes contents off because this takes a sequence and we're gonna say photo result dot photos all right and we're gonna say strong self dot delegate dot photo loaded so we're gonna call our delegate to let our delegate implementer know that hey we have new photos loaded so you might want to refresh yourself okay next case uh which is the failure case we're gonna get the error and print the error like that all right we should still be able to build and we'll build should succeed that means everything is looking good okay so we need um so we've got initializer now we need um a way for our table view that because this is going to be utilized by table view our table view needs a photo at index so what we can do is we can um basically give a function that can return the that can return the index and we can create this we can make this photos as private so we're going to create two functions uh so table our table we need two functions two things uh in order to uh act as a data source uh so basically uh table v data source needs count or number of rows that it needs to which it needs to be showing and the cell at index so we're going to create two functions one is going to be count or this can be a variable count and this is simply going to return photos.com and there's going to be a function and this function is going to be cut photo at index and this is going to return a photo okay so what you're going to do here simply return photo from that index all right so with that our view model is partially ready there are like you know 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 uh we're gonna basically create some functions to load images but let's first out let's first test out our api calls to see if they are working or not okay so uh in the next section in the next section we're gonna basically see how we can take the view controller and make an api call and see if we get any results back okay all right all right so first thing we're gonna do is uh basically check if our uh view model is uh returning the right response or not so let's go ahead and try that out so i have a home view controller open and we're going to create a viewmodel object here for listview model and uh then we're gonna basically assign uh the delegate self delegate uh for the v model and we're gonna say extension home delegate now we're going to implement the delegate there we go okay and whenever our photos are loaded we're gonna get the uh uh get this uh delegate method called and uh we're gonna be able to get the access to the photos so let's get one photo so we got photo at index zero and for this we can just print uh the photographer's name and url let's also print tag okay and uh with that let's go ahead and run this and there we go so we are getting photographer uh name here uh url and its tag so that means uh our api call is working just fine uh that's awesome so let's now go ahead and uh i'm going to remove this test code so we know everything is working fine so let's go ahead and start writing our view controller okay so uh what we're going to do is uh instead of uh having uh your table view and all the delegates and everything let's build out here we're gonna build them inside another file so we're gonna call this one um for the list view so it's gonna be another class so we're gonna simply create a swift file photo list view okay and uh inside this photo for the list view we're gonna create our uh table view and and uh basically the table view is going to host a cell and our new model and everything is going to be contained here so let's go ahead and import from ui kit we're also gonna create a protocol so we can propagate uh the uh event for example selection photo selection we're gonna let our view controller know that photo is selected so we're gonna simply create a protocol for that so we're gonna say photo list item selected delegate or yeah oh item delegate okay okay and it's gonna be a class inheriting class um and then we're gonna create a punk selected photo it's it's gonna take a photo so basically it's gonna give us the access to photo now we're gonna create our class photo list view ui view right oh we are delegate go to a list item delegate okay and we're going to create our model so let's give our new model and we're gonna make this view a delegate for the photography model myself okay next thing we need is a table view i'm gonna make this class data source and delegate for the table view and we're also going to register a cell so let's sell ui let's register your tip cell for now sale id all right 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 uh we can eliminate these errors so first we're gonna create photo list view photo list item delegate okay and photolist item delegate it's going to have this function okay and uh what do we want in this function basically we want to dispatch q main async and we're gonna reload their table view below data okay next extension ui oh sorry sorry photo list view ui delegate extension photo list view ui table view data source okay for the number of rows in section you can simply return remodel dot photos um.count okay so count has all the counts so we're gonna return that and for cell for row at index path we're gonna create our cell here so for now you're going to just return your table results so all the errors can go away okay go to list view model edit yeah photo list view model telling it that it's the way that we need this one and you're gonna start that one out and we're gonna do the same thing little takeout okay so this is going to be our data uh this is the ui to be delegate we can actually put functions uh when items are selected or we need to return the height so we do actually have a specific height that we want to provide so we can say height for item or height for row at index path and we're gonna return um 200 here okay so all of our cells are going to be up height 200 all right so that's going to be that okay so let's go ahead and try to build now and we should be able to build okay cool so that's awesome um now let's go ahead and continue our photo list view okay we're gonna have an initializer which is going to call super.init for frame 0 and it's going to call a function setup view okay all right setup v is not there so let's go ahead and create that and uh setup view is simply going to add the table view add subview table view and it is also going to call setup constrained another function that we're going to create so setup strings okay here uh we are going to be laying out our table view without a layout so we can simply say ns layout constraints so you can use anchor based constraints and we want to constrain our table view on the all sides of the view so we're going to simply say a b dot leading anchor dot constrain equal to leading anchor and i'm going to copy that paste it and i'm going to use this for trailing anchor as well for top anchor and for bottom anchor okay so those are going to be all of our constraints all right now um now what we need to do is basically set up our cell because right now we've just set up a ui w cell itself and uh that is uh that it's all right but that's not going to display our content we want to display in a custom cell so let's go ahead and define a custom cell so i'm going to create a new file photo cell okay and this photocell is basically going to be a class first of all you can import from like it go to cell on the ui table which i'll be the 900 we're going to create a function for on reuse so whenever reuse happens for the cell we're going to call this a function so it's going to be a closure which is going to be initialized it empty okay this is basically to get the uh review cell set up okay and i'm going to create our image view okay that's gonna be our image view and then we're gonna create our photographer level uh label this is where we're gonna show his name is our name always uh remember to set this uh translate auto sizing mask into constrain to false uh if you're using programmatic auto layout because otherwise your auto layout system will run into conflict because it will try to create constraints for you and you are also creating constraints so just remember this is like the most common error that you can make and easy to miss i'm going to set the text color to white okay and then we need photographers tag which is going to be pretty same we need water here i'm going to copy this and tag for tag label okay and uh it's gonna be our label constrain font size is gonna be 14 and color is going to be white awesome okay so now uh we can create a blur view uh the blur view that's uh gonna sit on the top of the uh image uh to show a photographer's name in his tag so we can essentially create a private lazy bar blur view circular effect view by visual effect view we're gonna give it a style dark let's let's create a blur view for this ui visual effect view that takes an effect an effect is basically blur effect and this is what we need to return before we returning before returning this we need to set translate orderly out to false otherwise it's gonna cause issues and we're gonna return blur view okay so that's our blur view now uh we are going to create our initializer for uh cell and we're going to call super dot init first and supply the style and the use identifier okay and then we're going to call setup view function here is all this is going to be another function that's going to set up this view and you can simply leave it like that now we need a required initializer so we're gonna simply click this and that's okay we can leave it as fatal because we are not initializing anything it's using storyboard and this is actually required whenever you are initializing views using storyboard so we can leave it like that so if somebody calls it type by mistake they would know that program is going to crash because it's not implemented we are not planning to implement it okay now setup we're gonna create another function set up uh setup constraints okay and uh 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 it for each on those and we're gonna say v in and uh we can simply take the content view and add sub view v so it's basically gonna add both of these views into the content view and then we're gonna do something similar for photographer label and photographer labels tag and we can say for each and we're gonna add these on blur effect view so flutter factory has content view and we're gonna add a sub view view the view that we are getting right here out of the for each loop okay so that's gonna add our views and then now we're going to set up our constraints so we're going to say let's layout constraint.activate and uh let's set up image constraints we're gonna have leading anchor for constraints equal to content view dot leading we want this image to be edge to edge so for the trailing we're gonna do the same thing continue dot training anchor and for the top anchor we're gonna have top and for bottom content views bottom so we're gonna make the image cover the entire cell then blur view let's add constraints for that blur effect view leading it's going to be constrained equal to content view dot leading anchor trailing is going to be constrained to content trailing anchor and then for the bottom we're gonna say content view dot bottom and we're gonna give this upload view a height high hiding height constraint so height anchor constrain equal to constant and we're going to say we want 50 point of height okay for the photographer label and tag we can have layout constraint we're going to use the overload that takes a constant so we're going to say blur view dot leading anchor with constant 2 right and it's going to give us a margin basically for the training trailing anchor we are going to simply say trailing anchor okay and uh constant is going to be negative 2 because if you give two it goes beyond the bounds of uh of the view okay and top anchor is going to be the photographer label stop anchor is going to be top anchor for the blur view with constant 2 and for for the photographer tag so let's add tag label now let's add tag label okay and tag labels leading is going to be the same as blur leading okay with two uh trailing is gonna be similar because you wanna anchor it for the leading and trailing the same as the photographer label the difference is going to be top and bottom so for the top anchor we're going to constrain it to photo photographer label dot bottom so whatever photo photographer label ends at the bottom with two points of margin and for the bottom anchor for the photographer tag label is going to be blurb used bottom anchor with negative two as the constant okay now uh one more one last thing we need to do in here is prepare for reuse prepare for views we're going to call super dot prepare for use first so let the table yourself do whatever the super class needs to do and we're going to call r on reuse yourself and you can also set image views image to nail okay all right so this is our cell that is set up now so in the uh in the next section we're gonna basically set up a wire up this cell to our table view and then start loading the images so start populating the data okay so cool all right so let's continue forward basically what we need is now we have our cell set up our photocell set up 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 uh we need to instead of like you know for the register instead of registering ui table view cell we should register our custom cell so we're gonna say photocell.self okay that will give it a type uh to register for the cell okay and uh next uh thing we need to do is basically get the row set up so right here sell for the row at index path okay so the way we're gonna uh set up row at index path is going to be first we're gonna get the cell from reusable cell so dq reusable cell so this ensures the performance of our table view and what we can do is we can actually create a static static static variable okay and uh instead of using this or we don't need static actually just create a constant that we can actually call it for all the instances so cell id here and we're gonna do the same thing here for cell id okay and we're gonna pass the index path that we have received right here all right now we need to cast this cell uh as photocell because what this 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 this casting right here it fails then we should return something so you can return ui table so this is gonna create just an empty cell okay um then next thing you need is a photo so we're gonna get to the view model and ask it for a photo at index path in index path at index and index we're gonna receive from index path dot row okay now from here on we just need to set the photographer label text so photo.photographer tag is put out for tag all right now um these are the label properties the text properties but what about the uh image right we haven't we have the image url so photo uh has under source it has landscape and portrait image url but those are just strings we don't want to actually pass strings but we want to show the photo now if we just render the photo like that that is i mean if you download the photo and we uh display the photo that's going to work but it's not going to play really well inside the table view cell because of the reusability aspect and the nature that table rose can be scrolled up or down so those images that were being downloaded they will download at a later time right and uh you're gonna run into an issue where your table is being used and then your image actually shows up because it was just downloaded so in order to overcome all that what we need to do is basically we need a uh we need some sort of image loader that can maintain in memory cache and basically whenever an image is requested using url we check if the image is present in the memory if it is we're going to return that otherwise we're going to simply uh make a call and return the image at layer point now we also need the ability to cancel the image download that way we can manage the state property and we proper properly and we don't unnecessarily download the image when the cell is not being displayed okay so for all that we're gonna create an image loader so i'm gonna right click on networking folder create a swift file we're gonna call this image loader okay and we are going to be importing from ui kit this is going to be a class h loader we're going to create two private variables first one is gonna be loaded images second one is gonna be running requests so the current requests that are running or that are being performed by the system for image download okay these two values these two variables we're going to use to maintain the state of our image loader so first one is going to be our cache second one is going to be all the running requests that are basically being performed for image download then we're going to create a function load image from a url and we're going to have a completion block and the image download is done and for the result we gonna get ui image in error okay now this is going to return this closure call is going to return void and this function call is going to return auid uuid is one uh value that we're gonna use for the cancellation purposes okay okay so what we're gonna do is uh we're gonna first check for the loaded image if for the given url an image is already present right if it's already present then we're gonna call the completion with success and we're gonna supply that image that we just found and we're going to return mail for uuid okay if that is not the case then we're going to create uid and we're going to create a task data task with url we can use and here we're gonna receive three things in the completion our data response error and we're gonna simply process them so first thing we're gonna do is uh we're gonna call differ for running request and remove value for key uuid which mean that whenever this task gets complete that means that that image has been downloaded so that operation is no longer running so you want to remove that uuid from the running request okay so if it's already downloaded that means the image is now in the cache so we don't need to cancel or anything because running request is something that we're gonna use to perform the cancellations okay so the next thing we're gonna do is we're gonna check if let data and let image from data okay if we get those then we're gonna simply call self dot loaded images and we can load or store the image inside loaded image and call completion with success and supply image return from here okay next we're gonna check for error if none then return okay if we got some error right we want to check if we can cast that error as ns error okay because we need the code if the ns error code is equal to you error cancel so basically we have already cancelled right then we don't need to do anything if we have not canceled and there's a failure a failure error that we got then we want to return that so we want to let our caller know that something else other than the cancellation happen okay and uh one more thing we need to do is first of all we need to remember to call fast.resume and we need to store the uuid inside our running request because now that request is running with this slide the request for that particular image download is running and we're going to return uid that's all now how are we going to use this uid well we're simply going to create a cancel 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 the running request now one more thing we need to make sure that we remove value for uuid that's all all right so this is basically gonna call our image make sure our image gets downloaded properly and stored and if there is any running request whose cell has been has been reused then we want to actually cancel those now that reuse part how we're going to handle that well that is going to be part where we're going to configure the cell right here so what we need to do is uh we need to set a flat url is equal to first of all get the url from string for photo dot source dot landscape so we're gonna use landscape a version of photo for the uh for the image cell for the photocell um and then we're gonna get the token first new model dot loaded okay so if you look at your view model you can get the photo right but there's one more addition we need to do into our remodel which is to download uh the image the access to the image right so what we're going to do is uh we're going to go to our view model uh photo list view model and we're gonna create an image loader so instance for image loader so image loader like that and we're going to initialize it right here okay now once we have initialized we can create a function that will load the image so we're gonna simply call load image function load image and you can create that with url this is gonna return a completion now here we're gonna call our image loader so image loader dot load image and we're gonna supply the url and we're gonna receive a completion with the result and uh here we're gonna put switch statement on the result itself because result gives us two values success and failure so we're gonna say success select image and we're gonna call completion with image in case of failure we're gonna print the error and return nil for the completion okay and the token that we get we're gonna return that token okay uh there's one more function that we need uh where we're gonna perform the cancellation so we're gonna create a cancel function that will take a token of type uid and we're gonna say if let token is equal 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 download the image from the network and give us a token so we can cancel the cancel the image request and all that code is now wrapped inside the viewmodel so all we need to do is call the viewmodel to load image for the url and we're gonna supply the url that we just got and if we get an image right we're gonna dispatch q go to main thread and we're gonna simply call cell dot image v dot image is equal to image in case you're wondering what's that image view that appearing whatever we type image v that is the image view that's fine default created for default cell um so which is that's why we created our our property as image v um not so not to overwrite the other image view okay all right so that is when our token is assigned our images loading now if during this time our cell is reused right then if you recall our photocell calls this on reuse on reuse function right closure call uh this is gonna call this closure call and the closure call is gonna make sure that if there is a token that we have received then we're gonna on the view model we're gonna call cancel for that token to make sure that our cell is ready to be reused okay all right so with this code we have our image download image download ready and our cells are ready okay so let's go into the home view controller and inside the home view controller we are going to create our uh we are going to add our photo list so we're simply going to create lazy bar photo list photo list view okay and we're gonna initialize that return view now remember to translate set translate auto sizing mask into constraint is equal to false and we also want to assign ourself for this view controller as a delegate for this photo list and delegate right so let's create an extension for home view controller photo list item target okay now this requires or creates a function selected photo so whenever the photo is selected um what we need to do is we need to launch a view controller so launch detail pc here okay so we haven't written that code yet so we're gonna write it when we when we have that uh selection uh selection operation ready we don't have it right now so we should be okay okay i mean we're not gonna do it right now but we're gonna come back and do it in a bit um let's call setup view function and create setup function okay this is gonna basically add sub view for our photo list and we're gonna call setup constraints okay here we're just simply gonna set up the layout constraint so activate and for the photo list we simply gonna stop he's simply gonna add it to constrain it to all sides so constraint equals to view dot leading anchor okay i'm gonna paste it four times i'm gonna put trailing anchor here top anchor and bottom anchor like so okay so with that our table view is ready let's go ahead and try to launch it and see what we got and there we go as you can see our images are loading and landscape views of landscape parts of the image unloading and if you notice our image our images are loaded when the cell itself loads so it's not it's not loading or basically creating that effect of like you're showing another image till the time one of the images being downloaded so it's loading the correct image into the cell itself okay all right so our image load part is done um now let's go ahead and uh set up our detail basically so we can tap on the cell and we can use delegate button for this uh so basically what's gonna happen is uh your list view is gonna have basically cell selection and it's gonna propagate that event using delegate uh protocol or allegation uh patent and uh then our view controller is gonna receive um that uh call the delegate call and it's going to basically propagate that to launch the view controller detail view controller okay so in the next section that's what we're going to look all right so let's go to our photo list view so we are already here for the list view right and in the photo list view if you scroll down um to where our view delegate right there will be delegated okay what we need to do is uh we need to have uh ability for user to select uh rows right so we're gonna say did select row at index path and uh whenever user selects a row we connect get the photo for that index path so you're going to say get photo at index path dot row all right and we're gonna call the delegate for selected photo like that okay so we're gonna simply propagate that uh to select it we are delegate and supply the photo now that photo is going to be received by the by the view controller that's implementing or the view that's on the class that's implementing this delegate which is this view controller right here so that's actually how you're gonna propagate this select event to your view controller okay now here we need to create uh basically a view controller so we can launch that all right so i'm gonna create a new file and we're going to create detail view controller import ui kit detail view controller which is going to inherit from ui view controller okay now this uiv controller is going to need muted load so we're gonna call super dot muted load all right and uh let's set the view dot background color to be white as well okay because uh when you view control is created programmatically it doesn't have any color so it's by default um it's just a empty color like you know clear color basically now this view controller is gonna need a photo so we're gonna create a property called photo okay and then we're gonna need a image and image view are we gonna display the image so image view ui image view okay and uh don't forget to transact translate our layout translate auto sizing mask into constraint to false and then p dot content mode is gonna be scaled aspect fill okay we're also gonna need a close button so although user can dismiss by swiping down it's uh better to provide a close button in if in case something else happens it's a good practice actually to provide a way out from your view even though there is a gesture that exists so we're going to create a ui button for that you can the set title for the button with x and uh the state is going to be normal set title color to be white for normal state and we also can add target of self with a selector now selector is an objective c function so we're gonna decorate with obj func so um yeah at opt c right and this is basically simply going to be up like you know a function that can be called using the selector so we're gonna say did tap close button and we're gonna dismiss animated true completion now and we're gonna call this dead tap close button for event touch up inside okay and we're gonna return our view which is gonna be close button okay now next thing we need to do is we need to add these two so we're gonna say v dot add sub view image view and view dot add sub view close button okay and then we're gonna create our layout so ns layout constraint.activate and here we're gonna first uh constrain our close button so trailing anchor dot constraint v dot trailing anchor and you can constrain it from negative 16 point from the from the training side close button dot top anchor is going to be constrained to you dot top anchor with 16 points so we have we we have like if this was our view we have reached here almost here so we can define close buttons uh dimensions for width and height so close button dot width anchor dot constraint equal to constant and let's say it's going to be 40 points and close button dot height anchor dot constrain equal to constant 40. okay so that's our close button now our image view is going to be image view dot leading constraint equal to and we're going to constrain this to all sides of the view so we're simply going to say view dot leading need this so we can remove that and i'm going to copy and paste this three more times one for trailing stop anchor bottom anchor like so okay now what we're going to do is we're going to basically when we receive the image we want to download the image right so we're going to say if let url so if we can get the construct the url from string and string we get from photo dot source start portrait now this time we're going to use portrait photo portrait version of photo okay and we're going to say we don't care about the cancellation because when we are loading this image this 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 gonna simply say result in switch result and we get the result and we can simply say success like image so we get the image here and we're gonna go once again the image always downloads and whenever like you know your session is called it's it's called on a different thread so you want to make sure whenever you're updating your ui that you are going back to the main thread before you update your ui so that's what we are doing here we are going to dispatch qr.main.sync so we can go to the main queue and then we can set the image set the image for our image view if in case any error we're gonna print the error and that should do it okay so that should basically download our image set our image and uh standard view controller now we go back to our uh home view controller uh that's where we are actually gonna launch this so like selected photo whenever this is called we're gonna set the view controller or create the object for detail view controller we're gonna set the photo to the photo that's been supplied to us by the delegate right here and then we're gonna simply call present and you're gonna present view controller animated true with the completion as now okay so let's go ahead and try to launch it and as you can see our selection is working and our close button is working if you notice the dismiss swipe to dismiss is also working and we are loading an image a footwork version portrait version of the image for the view right okay now to the part where we want to display um keep keep displaying basically keep the infinite scroll um that concept is uh that code piece of code is very simple so if you notice right now if you go reach to the end there's no more uh images so right images end here but if you want to have like you know load more image as the user is scrolling down uh that piece of functionality we need to add so that that is a simple technique um basically we need to implement a delegate call up for will display cell so we'll display so cell is called cell though all right let's call this play and we'll see okay we'll display sound right there okay so what we're going to do is we want to check if the index path dot row right if it has reached viewmodel.com minus 10 so basically whatever the viewmodel count is if it has reached 10 minus of that so like you know we only have 10 more images left to display for the user right then we want to call the view model dot load photos again now viewmodel.loadphotos what it's going to do is is basically going to increment the current page count page number right and it's going to call our photo feed with that page number so if the page number was one it's gonna increment and make the page number two and get 20 more images from the api and uh and then we can basically load those load those images populate our viewmodel and as the user is scrolling our images are gonna load so let's go ahead and try this out if it is working so if you notice we are scrolling we are scrolling and there we go we have more images loaded and keep scrolling and we have more images loading and if you keep going down uh going to basically load more and more images okay so that is how how easy it is to basically create uh infinite loading for your table view okay all right so with that we have reached to the end of this um end of this uh series so hope you enjoyed and you learned uh why oh and basically learned how to create an app uh that is completely created programmatically with the best ways to basically separate out your features so now you have like you know a photo list view and your home view controller if you look at like you know it has just few things now for the challenge uh you have two challenges basically first challenge is to create a view model and simplify this view controller as well so see if you can basically extract out all this ui related code 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 list view so try to do that that's first challenge second challenge is if you remember in our endpoint we had two end points um we had a curated list and we had a um we had a search list right for the enumeration and i guess it was the end point was at the endpoint uh maybe pixel client had that photo feed okay marbles inside the models we have photo feed okay yeah photo feed head search by category and curated now we have used uh we have used curated version to load display our image now your challenge is to basically create a segmented control here and inside this segmented control you have two segments one for curated one for search by category and uh curator is going to be automatically selected search by categories when you tab you can type a category or just choose a category if you want to hard code it and then basically let your user explore images based on that category okay so those are basically the challenges that you have to take for yourself uh implementation is gonna be uh similar to this so uh hopefully it's gonna go uh smooth okay all right so thanks again for uh watching i really appreciate everything uh and i really appreciate you guys support alright see you later
Info
Channel: DevTechie
Views: 979
Rating: undefined out of 5
Keywords: iOS Development, iOS, Swift 5.3, Full App Tutorial, Generics, Networking, Image Download, Swift Development, UIKit
Id: DsiB6VtHemc
Channel Id: undefined
Length: 143min 7sec (8587 seconds)
Published: Sun Dec 27 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.