Build Full News App in iOS & Swift Programmatically: Xcode 12, Swift 5.3

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Always love your tutorials. Looking forward to this one!

👍︎︎ 3 👤︎︎ u/mariozig 📅︎︎ Dec 31 2020 🗫︎ replies
Captions
hello everyone hope you're learning great and uh in today's video we are going to be building this uh news app from scratch and uh basically uh for to build this app uh we're gonna be leveraging news api um and a news api is basically a free api uh with i mean it's not free exactly is it has some pricing but it's free for tier so if you look at the pricing itself it is free for developers uh so you can actually uh try out and uh develop um for like you know trial purposes and then if you feel like you have a you have an app that you would like to uh basically launch into the app store then you can go about and and buy business licenses and stuff like that yeah anyways we are going to be uh leveraging this uh api to get uh real-time news articles uh from the uh from various different sources and uh basically uh we get these articles in json format so what we're going to do is uh we're going to build this app that is going to render these articles inside a table view and you're going to basically uh learn um a few things about like you know app building while actually developing this news api um and we're gonna go over the uh learning objectives of the course uh in a minute but let's check out the app itself so uh we're gonna have this uh table view and the header and uh basically this table view is gonna render out these these news articles and each news article has an image that is associated with that news article so we're gonna display uh that too so we're gonna learn how we can basically better cache our images and then uh you also uh basically gonna for example have a uh a detailed view and this detail view is basically going to be sf uh sf safari view controller uh sf survivor controller is basically a way for you to launch uh web pages inside your app and uh this actually uh gives your user a seamless experience where they are able to launch basically the uh web website or a webpage uh inside your app but they still have like you know ability to share like you know watch this on safari view so many other apps actually use uh this view and the benefit is that your app stays within the context so your your uh when you whenever you open this page your user can always go back to uh your app and that way you don't lose your user you'll still be able to provide access to the web via your um your your app but user not essentially walk away from there like for example like if you were to build a um an app that actually launches the url and if you were to open uh actual stuff mobile safari uh then you don't know if your user is gonna come back or not here in this case you are basically presenting your uh your webview other than that you're actually giving your user ability if they want to walk to safari and basically look at this page or bookmark it or whatever they want to do with it um but if they simply want to explore the page then they can actually do that and come back to the app so that's actually the biggest benefit that i see uh with sf safari view controller and okay so that's what that's what we're going to be building so once again we are going to have uh this news app built out completely programmatically uh inside uh ui kit okay so uh let's go ahead and take a look at the learning objectives uh for this um for this app so uh learning objectives are uh first and foremost it's gonna be that you're gonna be building a complete app and uh basically it's gonna be completely programmatically so there's no use of uh storyboards nibs so it's very similar to enterprise level development like you know where uh most of the companies don't uh adopt or don't actually go about uh using storyboards or nip files uh due to uh certain like issues that they run into over like you know in bigger teams um so we're gonna be like you know creating the entire app in uh basically programmatically and this actually gives you more um when you create your apps programmatically it gives you more understanding about the platform itself so you 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 you know 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 uh second thing uh is gonna be um basically ns cache so ns cache is a built-in cache that uh platform uh that ios platform itself provides uh for caching purposes and we're gonna see how we can leverage that to cache uh images okay and you're gonna see how easy it is basically for this caching and then you'll be able to access the cache to retrieve your images while reloading and everything so it actually works out quite well okay um other than that you're gonna be making a network api call to news api like i said and uh we are going to write a network a simple network manager uh which is gonna do uh basically two things exactly uh it's gonna make a call to json api for the news api and it's gonna make a call to images and cache those images inside in this cache uh we're gonna build uh the layout programmatically so all the layouts anchors and everything our layout stuff is gonna be programmatic uh you're gonna learn how to use mbbm within your project so we're gonna see how mbvm can help basically better um better manage your logic the business logic that you have inside your views you're gonna learn to build reusable views uh so we're gonna be creating a few views uh for example like you know there's gonna be a table we sell definitely most essential thing but other than that that uh you're gonna have like you know this header view um that's gonna be reusable you're going to create a component out of it and you're going to create this shadow effect image view so i don't know if you know this or not like or if you're probably encountered this thing that but ui image has a uh like you know an issue with uh dropping image dropping shadow so it's not that easy to drop shadow so we're gonna see how we can actually do that and we're gonna build a custom um view uh that'll have an image view with shadow in it so you're gonna see like you know how rounded corner and shadow works out for you so these are high level learning objectives uh that we have discussed here but there are like you know a whole bunch of things that you're gonna learn so um just follow along and uh have fun and uh we'll build this app from scratch um yeah yeah so um so let's go ahead and and get started and um i will see you next section where we gonna set up our project and get started with this uh app development okay all right so i went ahead and and created an empty project uh a ui based uh empty ios app and uh this app is um basically it has literally uh nothing um i've just uh created this and uh basically we're gonna uh start uh from here so um if you uh if you know like you know if you've worked with a storyboard you know that storyboard itself has an entry point marked by this arrow right here um and that entry point actually sort of uh the system knows that that this entry point is where the app is supposed to start so if you go in the scene delegate uh you're gonna find that uh scene delegate has not really uh leveraged anything uh down right here basically now everything happens behind the scenes so uh like to launch to even create like you know your view controllers and launch view controllers programmatically you will have to extend uh a bit more uh towards being given in the scene delegate so we what we're gonna do is uh under scene will connect um we are uh gonna take this uh underscore out and gonna type uh we need window scenes so we're gonna say window scene to basically programmatically launch our view controller so we're going to now initialize our window so we're going to say ui window and launch ui window with windows scene and i'm i'm gonna say this is the window scene that you that have been given to us okay and uh ultimately what he can do is uh let me show you the other way as well so what you can do is you can say window ui window and uh let's say if you wanna launch it with frame you can say ui screen dot main dot bounce and uh then you can initialize um then you can say window dot window scene is is equal to window scene that you have extracted out here from the windows cd from the scene from the current scene that's been given to us okay so that's another way to do it all right so let's continue with this way and uh all we can do is uh we can create our new controller okay um we're gonna create an object for that view controller and we're gonna say window dot root view controller is the view controller object that we just created and make sure this important uh don't miss this important step window dot window see a window uh make key and visible okay this is basically gonna present your view controller um so let's go ahead and give this you control right background so we got background color and i'm gonna do it red and just go ahead and launch this to see if we can get this this red view controller red view showing up okay all right so let me put this back in and there we go we have our ready controller 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 the storyboard uh deleting storyboard is gonna take a few things uh so you're gonna have to do a few steps for example um you're gonna have to first of all go ahead and remove this main interface right here from your settings um next thing you can simply uh right click and uh and delete the file itself and that's going to move that file into the dashboard so make sure you actually select move to trash move to trash can okay and uh i'll move to trash yeah um and then one more thing you'd have to do is basically go inside your info.plist and inside info plist uh you have application scene manifest and if you dig down this scene manifest you're gonna notice that um at at the scene configuration application session role item zero which is the default configuration there is a storyboard name uh entry right here so if you remove this entry and uh save your file now let's go ahead and and give our view controller background color maybe this time we're gonna give it white um oh not gonna notice if it's being loaded or not so let's go ahead and give it green and there should not be any crashes so there we go like we have our green view controller loading up that means like our our view controller is being launched programmatically now now if you launch without any background color you're going to notice that it's actually black so uh for that reason uh one thing that you can do is you can always set the background color to something so we're gonna set the background color to white okay let's go ahead and launch this and uh there we go all right so we have our view controller uh ready to go so next thing uh let's go ahead and check out the api itself so i'm gonna show you like you know what the api has so we can actually go ahead and discuss uh creating view models uh in the next section so um okay so news so first of all like you know just go to newsapi.org and get yourself an api key okay once you've got the api key if you are tempted to copy this uh feel free to do that but make sure that this is https so news api for some reason the the website itself has not updated that it's basically https it's support it supports https uh they have not updated these screenshots on these pages but they have support for that and if you put http and make a http call you're gonna see network transport layer uh error in your app um basically it's not gonna load uh for that you have to add um a an application transport their exception and that is not recommended because uh apple uh apple discourages any of the uh network call uh that is not secured so they actually uh uh they might reject your absolution on the basis of like you know uh on the basis of this fact uh that you're actually trying to make an insecure network call so uh just make sure all your network calls are on https okay and uh here news api does support that so just change copy this url and change this to http s okay instead of http and you should be fine okay uh next thing um so news api actually gives you a whole bunch of uh categories so we are going to be uh looking at this top headlines um and uh we can we're gonna be actually uh working on top here top headlines for country us so i literally just selected these uh this part right here uh but you can actually choose other categories and i would actually uh encourage you to build to extend this app further to provide ability to select different categories okay so that can be something that you can take as a challenge after you're finished with this series of course um okay so yeah so these are like you know a few things i wanted to mention uh next thing we're gonna do is once you get the api key uh go ahead and create a folder called config at the news api uh like for example i'm gonna create a folder right here and i'm gonna call this config okay and uh we're gonna create a new file here and we're gonna call this file api key okay and uh what this file is gonna contain is basically uh the api key uh that you're gonna get from the uh news api uh website itself so i'm gonna create a struct here api key and uh this is going to have a static variable called key and this is where i'm gonna paste my key okay this way um you get to keep your keys uh separate and when you know like you know you're checking in these um projects uh into github github repo or something then you can simply remove these keys from your code and security checking into public github or public domains and stuff like that so your key is not compromised okay all right so go ahead and do that step and uh then we're gonna start working on our uh news model okay all right so once you have uh basically your uh news api key set up now it's time to work on our on our news model itself okay so uh what we're gonna do is we're gonna construct a model and you can be leveraging uh json uh decoding or basic basically codable decodable protocol to um to basically decode uh these uh json response uh for us so we're gonna be creating uh so if you notice uh the json result response itself comes inside an envelope and uh basically the response itself is a dictionary uh that contains a status uh total results and an array of articles uh and we are essentially interested in this array of articles so what we're going to do is we're going to create an object to basically a decodable object for this this news envelope that's going to have the healthy other news articles and then we're gonna have a news object itself which is going to have these keys right here um which are going to be decodable so we can easily decode um or basically we can let the swift uh system or ios basically uh decode these for us just by conforming to decodable protocol okay all right so what i'm gonna do is uh i'm gonna create another folder right here and uh it's gonna be a new group and we're gonna call this one models okay and uh we're gonna i'm gonna press command n to add a new file and i'm gonna add a new file called news okay and we're gonna create two structs so i'm gonna just create two structs right here but if you wanna create like you know a separate file that's actually totally fine as well so i'm going to create a struct called use okay and it's going to be confirming to a decodable protocol now this news is basically going to have these keys the keys that we wanna the information that we wanna extract using decodable so we need author uh title description url to image and url yourself now the url to image is basically going to be used to download the image and a url itself you're going to use to basically launch ssf review controller to display that article on a webview okay so uh we're going to do is i'm going to create some properties okay so if you notice uh all of our uh all of our keys that we need are of string type so we are creating string and we are actually adding optionals for these because any of these could be it could be no so any of this information could be missing and what happens basically your decodable if you don't provide a an optional property then it thinks like you know it's it's something that has to be there so your there is a possibility for your decoder to fail and your app to crash so for that reason just for safety purposes because we are using third party uh api we know that like you know anything could be uh nil so in that case we're gonna mark all of these properties as as optional and we should just be fine with that okay now uh let's create this unlock that i was talking about now which contains the articles so we're gonna simply create another struct here use envelope and we're gonna have some properties so we have status which is of 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 can have that so articles it's going to be an array of news okay now these these uh keys have to be uh they have they have to be exactly same as what we have here there is a way where like you know if you wanna make your keys different uh you can use coding keys so go ahead and research a bit about uh decodable or portable protocol with coding keys and you're gonna find out um which essentially lets you change the names of these keys but for for simpler cases or for for a lot of time like you know you can keep it same and decodable actually works um works just fine for the decoding purposes okay all right so let's go ahead and check out our model one more time make sure everything that we need we have it here so we have author title description you missed your url and articles is a news array with total result as in type and status is strength and total results so the check is into type yes okay cool all right so that is all the uh all the things that we're gonna need uh for the uh for the model itself so uh let's go ahead and check out the uh network managers we're going to create network manager next and uh i'm going to make some all right so uh let's go ahead and create our networking layer so what we're going to do is uh we're going to create a new folder in new group and we're gonna call this one maybe services and inside this folder we're gonna create a new file so command n and i'm going to create a file called network manager and this network manager is going to be a class all right okay so uh there are a few things uh that we're gonna need first of all uh we're gonna be using ns cache for caching our uh images okay so let's go ahead and create a an image cache a variable called image cache and we're going to use nscache for this and uh ns cache is a generic type that takes uh types for of the key and the value so we're gonna say ns string is the key and ns data is the value that we're gonna hold inside um now we will create this network manager as a singleton so are we going to initialize it using a shared instance so we can create static let shared network manager and that's how we're going to initialize it now in order in order for us to prevent from anyone else or any other classes to initialize this we're going to create a private initializer and that is going to basically restrict the initialization for this um network manager okay now we are also going to need a couple of private properties um so we can need a base url so we're gonna say private let base url string and this is going to be uh the base url for the news api so in our case uh the base url is going to be this until v2 because everything else is a query so if you notice news api dot org slash v2 is a common between all the other types of api of uh news article categories right so we this is going to work as our as our base url okay so we're gonna take that and make sure to replace http with https okay uh we're gonna need another one um and i'm gonna use a us top headline in your case uh 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 user can choose different categories okay so we're gonna choose uh top headline country us okay so i'm going to copy that and uh that is going to be our uh category or subcategory basically uh other than the base url that's going to be our category for the news api call okay next we're going to create a function of get news this is going to take a completion handler of escaping type and it is going to return a closure with news array optional so news array can be empty and uh so we're gonna basically return nil if we encounter an error or something then we can return now uh here now alternatively you can use a result uh and uh a result api so i have another video uh i'm using this just to create a variation uh to show you like you know if you want to pass concrete objects basically you can do that too and this is the technique how you can actually pass the concrete object but um if you want to see how you can use result object in that case check out the other tutorial about building photos app and that actually shows you a generic way of making network calls okay all right so um here we're gonna first get the url string and we're gonna construct the url string by uh string interpolation and we're going to say base url string without any space uh we're going to add us top headline and then i'll be also going to need the api key so i'm going to say api key is equal okay and this is where we're going to use our api key file and we're going to say api key dot key okay so if you go back uh you're going to notice this is how we actually pass api key as a pretty so i'm string to go back and paste it make sure it's typed correctly and remove one equal okay there we go all right so that's done this is our url string now we're gonna put a card statement and if we can extract the url out of this url string uh then we're gonna continue otherwise we're gonna uh return from here so say guard let url is equal to url constructed from string url string now there's so i'm gonna i'm gonna keep talking about like you know the improvements that you can make or like you know challenges that you can take as a part of like you know this app building so you can improve upon things um it's basically one of the other things that you can do is you can have um this get news pass the url string instead of constructing it here so um so right now we are constructing url string here but he can actually ask user depending upon the category that they have chosen uh your function uh picks up a different url string um and that's being passed and then you actually try to extract it out if extraction or or url object creation is successful then you continue otherwise you return from here okay next we're gonna create a url session shared session dot data task are we gonna take the overloaded method that actually takes the url and has a completion block so we're gonna take this one this actually creates a task uh to retrieve content from the url and it has a completion handler that gives us data response and error so we can actually use that one so we can we already have a url so we're gonna pass that url here and for the completion block we simply gonna hit enter and we're gonna get data response in error okay so we're gonna check if the error is nil so card error is nil and we can extract data so data is equal to data if we can't do any of those then what we're gonna say um is completion is nil and we're gonna return from here so this is our indication in this case that we don't have any results and uh what you can do is uh there's not going to be and it's going to be called okay so what it tells basically uh what this tells us is basically if we have an error or if data is not present that means uh the completion block is gonna return a little that means no news article has been found now um you can further extend this by capturing the specific error and then display that error or or capture that error and have a backup basically a backup uh call to retrieve this from another source okay that's a topic for another day so i'm gonna just continue moving forward in this case and uh we are going to extract news envelope we're going to use json decoder and we're going to decode a news envelope from data okay and then we're gonna say if news envelope is nil in that case we're gonna say completion is going to be called with nil otherwise completion is gonna be called with news unlock dot articles okay let's go ahead and build this and see what's going on of course use envelope to be decodable okay so i guess you forgot to mark this decodable okay we can go back and we should have articles okay so since you're already checking for news article news envelope to be nil you can actually first unwrap or you can um you can simply put a card statement here and you can return as a part of card guard statement for the nil or completion handler with articles okay now uh the most important thing is to call resume so our network uh call is successful basically is made and data is being downloaded because if you don't call resume then this task is just gonna sit here um gonna do nothing okay um okay so it's time to test our network manager so let's go ahead and go into view controller and we're gonna say network manager dot shared dot get news with completion and we're gonna get news article here so we're gonna say if let or guard let news is equal to news else return okay if we found some news and you can simply take the first article and print its title uh just as a test to basically see uh if we are able to extract the news article out or not and then you can see uh we have a news article that we can extract out so that means our um api call is working fine okay so let's go ahead and remove this right and we need one more function here inside this uh network manager and that is going to be getting the image so we can cache that image from the url so we can create a function get image for the url string string with a completion which is going to have completion block with data and we're going to put guard let on url for the url string else we're gonna simply return a nail completion and return from here now if if we can get the cached image so we can say if let cached image so we can check our image cache first image cache dot object for key and we're gonna take our url string and then let's drop the uh string out so it takes a string url string okay so we're gonna basically do a lookup based on the url itself url string itself and see if the image already exists in the cache so if it does we're gonna call the completion right here with cached image as data because that's what we are actually storing as data and you're going to see what we are storing now so if we don't find the cache image we're going to make a call to url session for the shared session with data task and we're going to use our url that we have constructed right here and we will take we'll get data response error right we're gonna do the same check guard here is nil and data is present otherwise we are simply going to call nail completion and return from here otherwise we're gonna say self.imagecash.set object so we're gonna set the object for key okay so uh the object itself is going to be data and we're going to cast this as ns data because uh ns cache will takes ns data and ns string okay so you're gonna cast that as ns data and for the key we're gonna actually use hana string string overload and you're gonna pass the url string so that is basically storing our image in the in the cache and we can return as data as a completion block now don't forget to call resume and let's check out what we are doing here in this part okay so first time when we get a request to download an image what we're going to do is we're going to check um 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 object actually gives you data so if we have stored so uh for the first time it's not gonna find anything here so it's gonna go into this um else clock and url session is going to be called and it's going to make the network request and when it comes back it's going to set the image cache object and store data for key that is url string okay so that euro string key uh just like a dictionary is basically like a dictionary so it's going to store the url string as the key and data as the value and call the completion handler so we actually provide the caller data back but at the same time we also store that data inside our cache so next time when the same url is being called um for the same url image then we check the cache and say hey do we have this and if we do then return that from the cache instead of making a network call so that actually saves us a network call a for one call like say one one network call for one request right so if you have like you know users scrolling up and down like a whole bunch of times you have your images cached you don't have to make network calls over and over because your image cache cache is going to keep the track of all the images and it's going to cache all the images for you all right so that was our network manager okay so with that our network manager is complete so let's go ahead and check out um basically the uh view model creation first so we're gonna create our listview model and uh we're gonna see what else what are the things we need in listviewmodel and then we're gonna start constructing our views around the table be a solve okay all right so now we're gonna basically create our few models uh so we're gonna need uh two view models we're gonna use there's gonna be a list view model that's gonna be used for presenting the list now for each individual cell uh there is gonna be a table being cell and that wv cell is gonna have its own model for news articles itself so we can actually extract all the data out and instead of sending optionals we're gonna send the actual value so let's go ahead and see how we can actually wrap those things around inside a view model so i'm going to create a folder called view models okay and we're going to add a new file here i'm gonna call this file news view model okay and a new z model is gonna be a struct so which is gonna have it's gonna be called youtube model of course and it's going to take in use right and it's going to have some properties so for author so this is basically going to be a sort of like a rapper and uh for for our case uh i'm simply going to say if news dot author is present then send that otherwise send unknown right so uh this just to give you an example that you can have a another wrapper object which can basically sort of massage your data or 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 nail case rather than handling that little case um if the image is now replace 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 this so we're gonna create one for title if there's nothing then we're gonna simply return empty string same for description all right so url the image is 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 going to do is i'm going to use just i just google like you know a simple uh an image from kind png.com it's just a transparent breaking news png uh sort of related to the news news app and i'm gonna display that instead okay so if the new if the url is nil from the api then we're gonna display this image okay download it from this url so you can actually replace it with any other image your app logo or anything uh of that nature okay now that's our news view model okay now let's go ahead and create a list view model news list view model so i'm going to call this news list model okay and uh this one is going to be basically used by our view controller to basically get the news articles so i'm gonna create a class list model usb model we're going to use our new model that we have created earlier to 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 view model all the all the articles that you're gonna have receive are gonna be uh non-optional basically so you don't have to like you know um put that if it's present then do this and stuff like that you have much more cleaner way of handling your uh data that you have inside the object okay uh this is also gonna have a reuse id uh that we're gonna basically use as a salary use id so to use id is used now listview model can have anything that you can think of like you know that viewmodel can provide which can be reused so let's imagine like you know you have another view controller so right now you have a v controller that's showing a table view um but uh you want to provide your user ability to change that they would be into a collection view and show a grid uh layout right so what you can do is uh you can still have like you know all your ui logic built with a different view controller and up on the buttons click a different view controller view whichever it is um but on a button click uh you can change the layout but your view model uh stays the same so you don't have to repeat like that code so that's actually the purpose that that is uh that you're actually solving and the purpose for this listview model is basically provide that data source uh that does not change despite the layout changes okay so we're gonna create a function get news and this is gonna have a completion block of escaping and this is going to return void so it's gonna this completion block is going to return a news view model okay so we no longer are returning news we are actually returning usb model and here we gonna call our network manager uh shared instance get news okay and uh when we get the news uh we get the news array back not the news model and what we're gonna do is we're gonna say card let news is equal to news to make sure that we have something otherwise we're gonna return right but if we do get something then we're gonna say let news vm news view model and we're gonna map the news so we're going to simply say map okay and i'm not going to take so i'm going to take this initializer but i'm not going to build it like that so i'm going to simply say news view model dot okay and since this init is uh taking a news we don't have to like you know put that news in there it's just simply calling in it is gonna be fine so it's basically gonna take that first object then use object and put it into the newsview model for the initializer and get the viewmodel back okay and then we're gonna call dispatchqueue.main dot async now here we are actually moving ourselves into the main thread uh because network manager is called on the background thread so we're gonna move ourselves into main thread before we update the ui what's gonna happen is basically this function call get news is gonna be called from the view controller which is gonna reload the table view so we don't have to worry about basically changing the thread itself so you can wrap that piece of code inside your view model itself okay so we're gonna say self.news vm is equal to use vm okay completion news okay all right so with that our um our view models are basically complete uh next up we need to create our uh table view cell uh to display each individual news item and our header view and our shadow image view so all these three views that we're gonna create first so we can compose them inside our view controller with a table view okay so next up is going to be creating uh we're gonna we're gonna create our views first okay all right so let's go ahead and first create our header view so i'm going to create a new folder or new group here called views okay and inside this view we're going to create a new file and we're going to call this one header view okay and uh we are going to import from ui kit and gonna create a class called header view which is going to inherit from ui views okay now this header view is gonna take uh uh it's gonna have some properties some ui elements and stuff like that so let's start laying them out first thing we're gonna need is a font size then we're going to create our heading label so our and we can make this a final class because we know we're not going to further inherit from this one and the text for this one is going to be news for the heading and i'm gonna set the font to the font size okay um then we can have a circle image which is going to be a large circle so let me see if i can i think this is the all right let me launch the other app all right so this this circle right here uh this is what we're gonna draw and uh we're gonna basically get this uh from symbol so uh if you have as a single app uh open it and you're gonna see this uh image is called large circle fill circles so we're going to see how we can actually use sf symbol with a ui image so let's go ahead and create a private lazy we are adding circle image ui image view okay and we're gonna create our image view let's return this let's make sure it's translate auto sizing auto resizing mask into constraint is false so we provide the auto layout constraints not the system content mode let's set this content mode to scale aspect set okay then we're gonna create a config okay and this config is basically going to be ui image dot symbol config or simple configuration and uh this is where we're gonna define or give the point size so we're gonna say we need point size and weight so point size is gonna be the font size that we have and uh the weight basically bold and light and stuff like that so we're gonna say it's gonna be bold for the weight okay and then we're gonna simply create the image or set b dot image to ui image with system name with configuration so we're gonna use the overload that takes the configuration and uh we're gonna say the image name itself is that sf symbol uh 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 gonna basically create your uh image so let me actually resolve this error by creating let's create our own initializer that takes font size as the initialized duration property of type c city float and we're going to set this self.font size is equal to font size okay then we're going to call super dot init with the frame 0 okay and we're going to set translate is equal to false here and call setup view which is going to call setup constraints another function okay all right um and we need a required initializer so we're gonna leave it at fit error because we're not going to be initializing this using storyboard this is needed if you are initializing your view via storyboard okay all right so we have header circle image now we need that plus icon next to the image so we're going to create private lazy bar and once again we're gonna create our configuration and you can have the image and this time we are simply going to use plus h okay and um now there's one more thing that we need to set is we need to set the rendering mode for these so we're going to say rendering mode for the image is going to be always original so same thing goes for with rendering mode always rational okay all right so next we're going to create our uh stack view which is going to have this circle image heading label and plus image all these inside a horizontal stack view okay so we can create that and since you already have like you know all these views we're gonna start calling them so you can say heading uh first header circle image then heading label and then plus image in that order select the access for the stack view to horizontal and we're going to return them okay uh now we also are going to need this um headline this sub headline right so we're going to create a view for that for label for that so look at that you can set the font size that we have been uh given and uh now this is something that you can parameterize as well i'm actually just gonna code it here so top headlines and we're gonna set the text color to be gray okay so now uh we are ready to basically set the set of the view so we're gonna go ahead and go inside setup view and before setup constraint call we want to add subview first of all 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 view and all the other constraints all the other views are going to be constrained constrained or set up inside the stack itself so add stack view sub headline is actually outside so sub headline label is going to go as the sibling uh for the stack view okay and then uh setup constraints is going to be called and we're going to be setting up the constraints so first let's set up news header next layout ls layout constraints dot activate and this takes an array of anchors so we can say header stack view dot leading is going to be constrained to leading anchor and top anchor it's going to be the string to the top all right next uh we're gonna set the sub headline constraints so just to show you variation you can actually have all your constrained lists out in a single activate array or separate choices yours if there is no performance impact between these two so subheader is going to be constrained to the bottom anchor of the header stack view so we're going to simply say header stack view dot bottom anchor and we're going to space out by 8 points and then gonna say sub headline label dot bottom anchor constrain constraint to bottom anchor so okay all right so that was our review uh next up how we gonna create our uh shadow image and uh then construct our cell all right so let's set up our image view now so we're gonna create another file and this file is gonna be called shadow image view okay and i'll be gonna be importing from like it plus shadow view let's inherit from ui ui view okay and we're going to create an image here and this is basically going to be the image that user can set user of the shadow image you can set and whenever they set we're going to call date set observer and then we're gonna say image view dot image is equal to image now imageview doesn't exist so let's go ahead and create that let's make this as a final class of all okay and um get our uh gonna give it a corner radius of 20 and we're gonna say we need clip to bound to be true okay and then you can return our uh image view okay uh and that image views the image is going to be set whenever the image is set okay we are also going to need a base view okay that is going to go basically uh that's going to be the hosting view for this image view because uh what happens is uh whenever you actually try to add shadow to the image view because it's uh because you're clipping the shadow does not um you're clipping the view a shadow does not actually exactly render behind the image so what we're gonna do is we're gonna take another view uh stick it right under the uh image view and uh basically that base view is going to have the shadow so that's the technique that we're going to use uh to basically drop the shadow for the image view so i'm going to say private the easy bar so and we're gonna set the shadow color and stuff so we're gonna say ui black cg color shadow offset or width and height is going to be five points shadow opacity is going to be 0.7 shadow radius is going to be 10 points okay and uh that is going to be our base and then we're going to have our initializer now this initializer is going to call super dot init with frame as zero racked uh and this frame size is going to be basically determined once we have uh laid out our view so don't worry about like you know this zero right here because we are setting uh programmatic layout so this is all gonna work fine instead of view we're gonna create a function to set up the view instead of view it's gonna call setup constraints once the view is set up all right uh for the setup view uh we are going to add some view uh first base view so we're gonna add the base view on this um shadow image view right and then inside the base view we're gonna add our image view as something okay and uh then basically what we're gonna do is we're gonna say for the base view and for the image view we're gonna run for for each loop for each view and we're gonna say b dot leading anchor dot constrain equal to leading anchor and constant is going to be 16. so both of these are going to be uh basically because uh all the constraints are going to be same all the anchors are going to be same so we're going to simply put them in a for each loop and apply same layout for both of them training anchor now remember trailing anchor is negative value then you have your top anchor and last one is bottom angle let's go ahead and type this out and then we're going to see what the error is all right so connected lines okay what's going on here okay yep ns layout what about that and this layout constraint activate okay and this is where we are gonna activate our constraints that was the issue okay all right okay awesome so one more thing we need to do is uh whenever we are uh setting the uh uh we are laying out the sub views we need to call this layout subviews um function and we're going to call super dot layout surface first okay and this is where we can actually draw the shadow path if we draw the shadow path it's actually more efficient to draw the shadow uh for your app so that's why we can actually provide the path uh on which the shadow is gonna be drawn so we're gonna say base view dot layer dot shadow path is equal to ui bezier path and i'm going to use rounded rect which has a corner radius so we're going to say base view dot bound so this is the rounded rect and radius is 10 and we're going to say cg path on that so give us the cg path and we're going to say base v dot layer dot should rasterize so this is going to rasterize the view and we're going to say true and base view dot layer dot pasteurization scale is going to be the same skill that ui screen has so ui screen dot main dot scale okay all right so with that our um shadow image image view is uh finished and uh now we're gonna head on to uh the new stable view cell uh that is our last sub view basically that we're gonna create uh which is uh going to uh be uh representing individual cell uh this cell right here for our view okay so that is gonna be uh that's what that's what we're gonna all right so let's go ahead and create a new file and uh we're gonna create we're going to create news table sell okay import from ui kit all right and we're gonna create first our viewmodel then we can extract it out using a flat and then we're gonna set all the other properties here and this is where we're gonna make the network call sense and like in all the things okay um now we need a variable for news image data okay it's going to be a data type and this is also whatever dude that is called or whenever this object is set we're gonna say if let data use image data right we're gonna set the uh news image right here all right with that let's go ahead and create our controls so we're gonna have image view using image first so private lazy you are and we're gonna use our shadow image okay and uh here whenever we are getting news image data we are gonna set news image dot image is equal to ui image with data that we have extracted out okay now that is news image next we need title label gonna set number of lines for this title label to be zero so we can fit multiple lines uh and this is basically uh the title um for the news so this section right here and uh this can be as long as basically the api returns that's why we're going to set the number of lines uh to be zero so cell can expand depending upon how many lines it needs okay um now we're gonna basically initialize and we're gonna use the initialized overload that has uh that takes a cell style and we use identifier we're gonna first supply this information to the super class is saying this is the style that we got and we use identifier okay next uh we are going to basically set the selection style selection style for the cell to be none so you don't show that gray like light light gray selection or tab um highlight uh we actually just uh are gonna set it to none okay next we're gonna call setup view okay and uh this is simply the function which we'll call the strings okay and we do need a initializer from the quarter we're not going to implement that all right now for the uh setup view now we are going to add some view that's going to be the title label and news image okay and then we're gonna constrain it so use image constraint here we're gonna have use image dot leading anchor dot constrain equal to leading anchor okay uh use image dot training and our news image is going to have a height which is equal to a constant that height is going to be 200 okay and then your title we're gonna have training and bottom okay so leading is going to be leading trailing is going to be trailing anchor negative 16 and top anchor is gonna be basically news image dot bottom anchor and that's gonna be eight point of um gap between those and for the bottom it's going to be the bottom anchor with negative 16 as the uh constant okay and with that our table view cell is uh also complete so next up we're gonna put all these together inside our view controller and construct our table view all right so with all the components in place it's gonna be um rather easy for us to put together this view so what we're gonna do is uh first of all we're gonna need uh to import uh safari services uh because we're gonna be using sm safari view controller um and uh uh that's where uh it's actually defined under safari services module so that's how we're gonna include that right then uh we are going to need uh to create a uh an object for our view model so we're gonna create new model object use list view model okay and uh we're gonna create a lazy bar property for our header view which is gonna be header view the view that we have created and simply we're gonna return create that view add a view of font size 32 and we're gonna return that okay we are also going to create a uh so these two can be private because you don't need to give access to these anywhere private lazy bar table view and this is going to be y table you and return view and we got translate us let's set the table footer view to ui view so we don't have uh order view showing empty cells and we're gonna register a class and this is going to be basically our news table view cell news table view cell class dot self so we're going to give it skype and our view model has the reuse identifier so we're going to use that we use identifier to register register that cell we're going to create uh we're going to set ourselves for the delegate and data source and yeah so now uh the uh compiler is complaining about these delegates not being uh our view controller not conforming to these uh delegates so let's go ahead and create an extension or view controller for ui table view delegate and ui table view data source okay and uh you're gonna have number of rows in section and uh here we're gonna simply say uh just return view model dot news viewmodel.com okay so that will give the uh number of rows and then sell for row at index path and uh basically this is where we're going to construct our cell we're going to say table view dot dq cell that's reusable identifier for index and we're going to say this is going to be view model dot reuse id or index path and this is going to be as news table you sell okay so we're gonna return cell if we cannot extract or dequeue a new sell out then we're gonna return an empty cell so ui table you sell like so okay and uh here all we need to do is get the news so we're gonna save you model dot news remodel get the news for that index path dot row and we simply gonna set the news remodel 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 um that i forgot about they will be cell itself is vr we did not set this uh news beam out so let's let me fix this um i just realized that we are actually creating all these things but we are not setting anything so our cell is going to be empty uh despite data being there so we're going to simply say title label.text is going to be news vm dot title okay and here we gonna make the call to get image so we're gonna say network manager dot shared dot get image and we're gonna get the image from news for the url string from news view model dot url to image and this is gonna give us a data back now this data is uh we are that we're going to use to set the image so we're going to first say guard let data is equal to data else return dispatch q dot main dot async so we're gonna move to main thread once we get the data and we're gonna say self dot news image dot image is equal to ui image from data like so okay so that is going to make sure that we have uh data being downloaded image being downloaded and we actually display that into the cell so continue forward into our view controller so our cell is set okay so our error is gone now okay and we're gonna come back to the view did load function and we're gonna set setup view function or call setup view function which does not exist at the moment but we're gonna create that and uh we're gonna call a set of 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 i'm going to call this patch news and this fetch news is going to call our view model remodels get news and get news gives us a completion and we are simply going to call table view dot reload here or not respond to rather reload data okay whenever we get the news back right so uh for the side of view we are simply going to first of all we're gonna move this guy into our setup view call okay and then we're gonna add sub view our header view first and then our add for the constraints for header we're gonna say ns layout constraint dot activate so we can use safe area layout guide for the top and we can say constant is 10 for the top okay so those are going to be the header related constraints then table view constraints right so that is going to set all of our constraints okay so with that let's go ahead and try to run this all right so if you notice uh we have uh our images showing up but they're looking rather ugly uh reason is i actually mistyped this um to be scaled aspect fill instead of um which i should have like typed fill instead of fit okay so there we go and as you can see our um 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 could not 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 event so let's go ahead and go into our view controller and all we can do is uh we are going to provide a selection so um on the table we gonna say did select row at index path and uh basically we to get the news article that was being um that was being tapped on so we're going to say news view model get the item for index path dot row you're we're gonna put the guard let for the url to make sure that we can actually construct a url and we're gonna get the news url this time so we need actually the actual url for the news article so we can launch it inside our webview and next we're going to create a config for safari viewcontroller dot configuration okay and then we're going to create our safari view controller it says safari view controller and uh we're gonna pass the url and the configuration so url and config now we have a choice so we can uh we can present this um basically with the model presentation style as a form sheet so let's check out the form sheet and then i'll show you the other way where you can actually um you can launch it in full screen so present um safari view controller any major true and we don't need this so we can just simply remove that okay so now let's go ahead and launch the app once again and um what we're going to do is uh whenever uh so we have this uh uh downloaded uh news article right uh we're going to select that so we're going to select it and there we go we are launching our webview inside a inside a form sheet right now in case if you want to basically uh get this um loaded in into a full screen so you can say full screen right there or any other mode or model presentation style that you may uh prefer okay so when you launch it as a full screen it's gonna basically launch inside this view and you have all the other options now this is a fully functional browser right there and uh uh what whichever view you load is actually gonna show all the information right there and if you notice like safari view yourself comes with a lot of things so when you start scrolling it actually hides away safari view so user gets the maximum view uh area uh out and as they're scrolling up uh the controls show up show backup right so that's actually one of the one of the nice thing i really like about um about this sf safari view controller all right and uh with that we came to the end when and we have built an entire app entire news app with various different things that we actually put together and uh hopefully uh you found things interesting and you learned uh from uh by building an actual app um so hopefully you found this uh useful and thanks again uh for um uh joining me in this journey and building this app so thank you so much i will see you guys in another series
Info
Channel: DevTechie
Views: 3,606
Rating: undefined out of 5
Keywords:
Id: Wu3er4AMG8U
Channel Id: undefined
Length: 98min 4sec (5884 seconds)
Published: Wed Dec 30 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.