Swift: Side Menu from Scratch (Swift 5, Xcode 12, UIKit, 2021) - iOS Development

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's going on everyone welcome back to the channel in today's video we're going to learn how to make a slide out side menu from scratch so here's the app we'll make we got this nice button up here and when you open it up as expected you've got this menu so we'll take a look at that in addition we'll actually take a look at hooking up these options because i think a lot of videos show how to do this but the actual important piece of switching controllers isn't really talked about so this uh this is all built with professional kind of pattern in mind with different controllers and making sure things are nice and organized uh between different view controllers and child controllers so if that all sounds good definitely start by destroying the like button down below subscribe to the channel if you're into ios and haven't done so already let's get into making this side menu from scratch all right we're going to go ahead and get started by opening up xcode and creating a new project we're going to stick with the app template under ios and let's go ahead and give this a project name of side menu make sure your language is set to swift lifecycle ui kit and interface is storyboard even though we're going to work programmatically we still need to start off with that go ahead and save the project wherever you like i'll toss it onto my desktop and first things first we're going to expand the window and close that right panel now the other thing that we need to do before we jump into the side menu code is right click our main.storyboard hit delete and hit move to trash now we also need to jump into our info.plist and hit the main storyboard row and hit backspace to delete it we also want to open up this application scene manifest until you get all the way to the bottom and delete the main storyboard reference in there as well and the other thing i'm going to do is actually rename this view controller to be a container view controller and i'll also change the name of the file here now to make sure that we're going to be using that container controller instead of the storyboard we need to jump into our scene delegate and in the first function here we want to go ahead and set up our applications window so i'm going to say window is ui window with a windows scene window dot root view controller is going to be a container view controller and then we're going to say window make key and visible and then finally self done window will be window so let's go ahead and do that and before we actually go further let's make sure our app is working so in here i'm just going to set a background color perhaps of red go ahead and pick a simulator of your choice and hit run to make sure that our app is nice and happy now that we've deleted the storyboard and then we'll jump into some side menu implementation so bear with our simulator here and boom we've got our red screen so we're in business all right so let's talk about how we're going to build out our side menu so what we actually want to do is by the name it probably implies it in our container controller we want to have two view controllers and one is going to represent the actual content and the other one is going to represent the menu itself so that said what we're going to do to keep things nice and organized is i'm going to create a new group on the left hand here now we're going to create a group for view controllers and drag in container into here let's go ahead and create two new files in here the first one and actually what we can do is use a cocoa touch class is going to be called a menu view controller of type ui view controller and then we want one more and this other one is going to be a home view controller once again of type view controller so inside of home view controller let's get started by deleting all of this jazz here and i'm going to go ahead and say view dot background color is perhaps system background i'm also going to give it a title of home and let's go into our menu and in here we're also going to delete all this commented out code and we're going to give this a background color of ui color with red green and blue and we're going to say 33 over 255 which is a pretty dark menu looking color so let's go ahead and copy and paste then alpha will be one now if we jump back into our container view controller what we want to do is add both the menu and the home as child view controllers so i'm going to go ahead and say add child vcs right here and what we'll go ahead and do is we're going to create this function and what i'm going to say here is we want to go ahead and first add the menu so it's the bottom controller in terms of the z-axis and then at home on top of it now to go ahead and actually do this what we can say up here is lazily create reader doesn't actually even have to be lazy we can say menu vc is the menu view controller and if autocomplete is giving you a hard time go ahead and hit command b you might sometimes need to close xcode and reopen it and your autocomplete will get its life together so you saw for me at least uh xcode is deciding to be difficult i like leaving this stuff in the video because we all love the pain of xcode here but let's also go ahead and create our home vc which is going to be a instance of our home view controller and now that we have both of these here here we can say add child of menu view controller we want to go ahead and say view add sub view of the menus view then we want to go ahead and say menu vc did move to parent of self because the menu controller is now a child of this container controller so looking pretty good we're going to do this exact same thing for the home controller so we can say add child home vc we're going to then add home vc's view so we'll say view add sub view and we can add in home vc's view but actually instead of adding home vc's view what i'm going to actually do here is we're going to say that there is a navigation controller that's going to wrap home view controller and the reason is is because the navigation controller will give us the bar and the title at the top but once we've gone ahead and done that we can say nav vc did move to parent of self so go ahead and give your application a run and what we expect to see now is our white view controller with a navigation bar at the top with our title of home so bear with us bear with us simulator loves to be slow but there is our home header right up there looking pretty solid so the next thing we actually want to do is have a button at the top left here that we can tap on to open up our side menu so that's going to be in the home view controller all we need to do here is set a navigation item and it's left bar button item it'll be a ui bar button item with a image style and a target action so we're going to say the image is going to be a system name i will grab that momentarily style will be done target will be self and action will be a function that we create so selector to tap menu button so we'll come back to actually implementing this function here that will stub out momentarily but the first thing we want to do is open up sf symbols this is apple's icon library for those of you not familiar so we can actually grab any of these here there's quite a few to choose from some people like line horizontal i'm going to use this bulleted list one so you can go ahead and copy the name of it and just paste it in right here and let's see if we give it a run what this ends up looking like if we see our menu button or not so we definitely see our menu icon right there tapping it right now and nothing happens so what do we want to do when we actually tap on this well the tricky thing is we want to basically animate to this home controller in the container so it reveals the menu behind it but these controllers are separate so how do we communicate from the home back to this container for those of you familiar with this concept you know that we're going to use a delegate so i'm going to create a protocol up here which is going to be the home view controller delegate and it's going to extend any object and it's going to have a single function of did tap menu button just like that now we're gonna have a reference of the delegate on here which will be weak so we don't cause a memory leak and we can now say here in this function is delegates and called the only delegate function that is available so now what we want to do is we want to make this container view controller a delegate for the home controller so we're going to write a extension for the controller the container view controller conforming to the delegates and we'll bring in that single function here now in here we want to animate the menu itself just like that but how do we actually get that working well the first thing we want to do is actually assign that property on home vc so we'll say homevcs.delegate will be self so go ahead and let me actually add a print in here so we can actually validate that we are getting this function call so let's go ahead and run our app i'm going to tap on this and you can see right there in the bottom that we are indeed printing this uh message in the console every time we tap on it now the more interesting thing and the more important thing that we want to do is we want to animate our actual menu so how do we do that um so what i mean by that is the menu is going to actually stay put since it's behind this but what we want to do is make it look like it's revealed so we want to actually move this home controller so the first thing i'm going to do is create an enum in here and it's going to be called menu state and it's basically going to have two states as you can imagine open and closed and what we can do in here is have an instance of this so the first one is going to be private var menu state will be menu state and by default on our app launches it's definitely closed because it's going to be kind of weird if it's open by default and what we can do in here is we can switch on the menu states we can say if it's closed we want to go ahead and open it and if it's opened we want to go ahead and close it so let me go ahead and add in some comments here so looking pretty good so what we want to open now all we really need to do is do an animation so we're going to say animates with duration so there's a couple different animations we can do there's also one in here with a spring velocity so let's see if i can find that one that one actually looks pretty nice as well so let's do this one here we'll see the duration is 0.5 delay is zero spring with dampening is 0.8 you can tweak these numbers and you know see how they feel initial velocity is zero and for options you can say curve ease in or ease out it'll just make it uh you know be a little slower when it animates when it starts and then you know stop so it's not so linear and then our actual animations we'll need to do something here and we want to do something in our completion as well once it's done so what are our actual animations going to be well it's pretty simple we're going to say self dot home vc dot view and it's frame origin x and what we want to go ahead and actually do is just move the origin x over so what i can say here is make this the entire width uh subtracting maybe a hundred so you can do this calculation in different ways it's a little subjective let's just toss a break down here momentarily let me give this a run so you can actually see what's going on so we tap on this guy here if you look at that the whole thing just moved over so one thing which is a little problematic is well what the heck just happened here this view moves but the title bar didn't so that's not what we want so what we actually want to do if you recall up here we have a property for home vc but we also want to hold a nav vc since we're nesting the actual home controller inside of this navigation controller so here i'm going to say self.navvc is going to be nav vc and down here we can animate the navigation controllers view adding in the question mark since it is optional so go ahead and tap on this and now this whole thing moves over now when we tap on this again nothing actually happens because we aren't handled handling this yet and the other thing that we want to make sure we do in this completion block is first capture week self and i'm going to say for self dot menu state once the animation is done it's now going to be open and make sure it's menu state there and now this is pretty simple we want to do the inverse to close it so first and foremost once this is done it'll be closed and the origin x now is going to just be zero like it was before so go ahead and uh right give this a run once more we tap on it we tap the button again it closes pretty darn cool so the next thing we want to actually do is actually put something in our menu and we tap on one of those options we want to be able to come back and switch controllers in this primary ui here so that's pretty simple as well so let's jump into our menu view controller and you guys can do this however you want using an enum is pretty a pretty useful way to do this but you can say menu options and there's going to be a raw value of string and it'll also be case iterable and i'm going to go ahead and add a couple cases in here so we'll go ahead and say uh home let's see home about us information rates uh app we can just say rate and let's see for this about us of course we need to do this so actually let me be cleaner about this what you probably want to do is assign the actual raw value instead of cheating generally these shouldn't be capitalized so we'll go ahead and just type these out and assign them so we'll say case info will be in formation the one thing you do want to be aware of though is that the order of these do in fact matter so the order that you put these in here we're going to use case iterable to maintain this order so just be mindful of that so just order them the way that you want it to show up so let's put settings down at the bottom actually so there is a list of options here so what we can actually go ahead and do is uh we want to create a table view in here so i'm going to say private let's table view will be a table view in here and we're just going to register a vanilla table you sell we're not going to use any custom cell here you could in fact use a custom cell if you wanted to but we're not going to do that today since honestly a pretty plain vanilla cell actually looks pretty good so we're going to go ahead and say view at sub view table view we want to assign the table views delegate as well as its data source and similar to any protocol or delegates you need to go ahead and conform to all that stuff so delegate and data source now we want the table view functions so the first one is going to be number of rows pretty simple we're going to take our menu options dot all cases dot count and in terms of the next function we want cell for row at index path and we want to dequeue a row from the table of type cell for a given index path the one that is the parameter we're going to say return cell and here we can say the text is going to be menu option dot all cases and we want to get the nth position dot raw value so that'll basically take is it'll take whichever option we're at and it'll give us the string as the text now the third function we want is did select row at index path and the first thing we'll do in here is say table view go ahead and deselect it aka un highlight it so let's see what more we need to do we also want to go ahead and give our table view a frame and if you did layout sub views so i'm going to go ahead and override that and assign the frame here so we're going to say table view its frame is going to be x0 y will be view dot safe area in sets dot top this will be view dot bounds dot size dot with and this one will be view dot bounds dot size dot height now go ahead and give this a run i know i went through it pretty quickly but i'll explain it again let's go ahead and see what's going on so first and foremost we are crashing which is not good so let's see why we're crashing and debug this together so let's see it's yelling at us invalid argument for our actual cell which leads me to believe we did not register it correctly so let's see where my typo is here we should be registering a cell dot self not a table view itself i'm sure a lot of you guys saw me do that and were pulling your hair out so if we go ahead and hit this you'll now see we've got our table of you showing up one problem i see here is every cell in the table itself is has a background color of white so the one thing i'm going to do here is say table dot background color should be nil i'm also going to do that for each of these cells here we'll say cell dot background color is nil and if nil isn't really you know the desired look that we want we can also go ahead and assign the background color but i'll also nail it out for the content view right so looking better so one thing i see now is the table view itself still shows that white background so what i'll actually go ahead and do is we'll assign the same background color we did to this controller as the cell background color so i'm going to call this a gray color i will go ahead and make this a global up here we'll say gray color is our color like that and down here instead of nailing these out go ahead and use gray color and gray color for both the background of the cell and the content view all right so the one problem i see now is we want our text to always be white since we're going to always have this uh the menu be a darker color so we're gonna go ahead and say this is white and i also want this to have a nice icon to the left of it because what are menus if we don't have icons so what i'll go ahead and do is i'm going to create a computed property here called maybe image name in our enum and we are going to switch on self here and i can actually let the error that pops up here in a moment input everything for me you can click in and hit fix and we're going to return basically a image name for each of these so the first one here will be a house this one i guess can be i don't know airplane i'm kind of making them up at this point this one will be a star uh this one will be a message that should be star and this last one here will be a gear now these are all sf symbol names so you can open up the reference and take a look but now what we can do down in our cell configuration is we can say cell dot image view dot image can be our menu options dot all cases dot index path dot row and we have an image name here now this is a string so we need to take this and wrap it inside of a ui image call just like that and we're also going to set the tint color on the image view to be white so it matches our actual text so go ahead and give that a run let's see what's going on looks like we've got an issue here so let's see what i forgot to do i forgot to put the return keyword right there before star go ahead and give that a run and you'll now see you have a pretty cool looking menu at this point now when we tap on these something should happen and clearly something isn't happening so let's go ahead and hook that up so very similar to our home controller using a delegate we're going to create a delegate for our menu controller as well so it's going to be a protocol right up here and i'm going to go ahead and say funk and here we're going to say did select we're going to use a menu item so we're going to say did select menu item and this is going to be our menu view controller dot menu option just like that and then we're going to create an instance of this here which is going to be a weak var of type delegate and once we actually select on an item what we can do is say the item that we got is our menu options.all cases get the positioned item that we tapped and then we can call that delegate function passing in the item so now we want to actually go back to our container controller and our container controller should assign the menu vcsdelegate to the self and just like we conformed down here with this extension i'm going to actually copy and paste it we're going to conform to the menu view controller delegates and it's going to have a single function in here so let's see if my autocomplete will do its job there it goes and now what we can do is we know that we want to actually go ahead and close uh the view controller for the menu so we can actually call did tap menu button and it's a little bit of cheating in terms of the naming because you're not actually calling the menu button so you might want to actually go ahead and create another function albeit it's going to be the exact same code but there is one distinction so when we are actually done with this we can actually call a completion handler where we'll present a different controller so what i mean by that is let's actually move this code into a dedicated function of toggle menu and it's going to have a completion handler and this completion handler i'll say is uh nothing to returning void and what we'll do here is we want to first and foremost call this here so we'll say toggle menu and we don't want anything in this case so what i'll actually do here is we're going to say that this completion handler is optional so we call this function from here we can pass in nil and then now here what i can actually do is call toggle menu but in this case i do care about a completion handler because once we're done animating what we want to do is we want to switch on the menu item and we want to go to a different view controller depending on which item was selected so i'm just going to do the a different example for one of these i'll put a break in the rest of them so what i'll actually go ahead and do here is let's break that as well is we want to first call this completion in this function up here for toggle menu so we should be closing the menu at this point so what i'm going to go ahead and do here is we're going to say that at this point call the completion now you might see an error here and the reason for it uh is because this needs to be escaping but since our closure is already optional you'll see that we don't see the error because optional closures already are escaping the one other thing we do want to make sure we do is call this on the main thread because this might execute asynchronously on a background thread and since we want to present a different controller here that's a ui operation that we'll want to do on a different on the main ui thread so let's see that said let's see what else we need to do we're going to capture weak self here and what we'll want to go ahead and do here is present a different controller so let me go ahead and create another controller we're gonna right click this new controller i'm gonna go ahead and create a info view controller now all i'm gonna really do in here is uh just say title is going to be about this app and we'll maybe also give it a nice background color of system green perhaps and get rid of this comment so now we can do back in this controller is we can create an instance of it so we'll say vc is our info controller and you can do one of two things i'll show you guys both approaches we could present this controller so i could say self dot present and i'll wrap it in a navigation controller with a root controller of vc animated true and let's see this one should be yup animated true and completion of nil so go ahead and let's go ahead and open up our menu and i'm going to hit in this case we're going to hit on information it closes and notice that nothing is being presented so let's figure out what the heck is going on that's incorrect so the first thing i'm going to go ahead and do is we're going to print out did select so we know for a fact that this is being called because the menu is in fact being closed but what's not happening in this case is we're not seeing that green controller so let's also go ahead and make sure our completion is being called so we're going to go ahead and say completion and these print statements are often very helpful to debug so we'll go ahead and hit this i'm going to go ahead and do that and we'll see that it's selected but completion is never called here so let's see what the heck is going on so we're saying that if it's open we want to close it so i put this in the wrong place so this is why comments are always helpful so we want to call completion once the menu is closed because we want to present once it presumably closes so go ahead and do that and we should now see our green controller so that's a good way to navigate however there's another thing which is commonly done and that is instead of presenting something modally you might want to change out the primary view here so there are a number of ways you can do that the first one is and the most common one is using child controllers so just like we used the home view controller up here we can create a info vc and in this case we're going to say this is lazy so we don't create it as soon as the app launches and in this case what we can now do is we can say add info child so what i can say here is say self dot info vc we can actually unwrap it and say guard let vc equals info vc and i'm going to go ahead and say self dot add a child for view controller and then what we want to go ahead and do is assign the views frame and we might want to actually add it as a sub view first so i can say vc dot view and notice that we're adding it to this view here so this might not actually be suitable so what you want to do is actually add it to the home vcs view and you'll see momentarily why we want to do that then we want to say vc did move to parent of self and keep in mind we still need to give a frame to the view controller that we are adding so it's going to be vc view dot frame and this is going to be the frame size of the home controller so we'll say this dot bounds so let's see that's going to be optional so we'll coalesce it to zero go ahead and give this a run and let's see what ends up happening when we tap on the menu option so we'll open this up we'll tap on this and we expect to see a green controller there so let's see what's actually going on here so let's see on caught exception ui view controller inconsistency reason child view controller should have a parent view controller so let's see what's going on so we're saying self add child that we're saying to this view add that we're saying vc did move to self now this self keep in mind we're capturing weak self here so what we want to actually do is say guard let's strong self is self and this is all because we are inside of a closure so go ahead and i presume what the option or issue here is is we're passing in weak self or we want to pass in strong self so let's go ahead and give that a try and let's see what's going on looks like we are still crashing so something is up here so we're saying vc is our info vc we're adding view controller we're adding vc's view we're setting its viewframe and then we're also going ahead and we're saying vc did move to parent for strong self so let's see what's going on what i'll actually do is let's make a cleaner and say self add info and i'll go ahead and create this as its own function just to make it a lot cleaner to actually read here so we are going to say i will be able to actually drop this guard we actually don't need this either and let's make our life simpler first and foremost so we have our info view controller we no longer need all these self optionals we're going to say add child for vc let's go ahead and add this to view we are going to say vc did move to parent which is going to be self and here we are going to say let's just use view dot frame and let's make sure our green controller is first and foremost showing up so go ahead and give it a run and if we continue to have issues we can debug it together but we don't because it's now showing up so sometimes doing things in a closure is a little tricky or i probably had a silly typo but one issue we now see is we don't see that button anymore up here so what gives that's not that good so that's why we wanted to add this as a child of our home controller so you could add it either there or to this one directly so let's try adding it to our home vc we can say add info vc as a child we're going to say home vc to its view go ahead and add a sub view we're going to assign vc's view frame and then we're going to say home vc did move to parent self which is not what we want we want to say vc did move to parent of home vc so once you have a bunch of controllers it gets a little hairy so make sure you name things more appropriately i just kind of named it in a not so great way but now if you go ahead and tap on it you'll see that the green controller even though it's completely separate from home is now showing up here but we still see the title of home at the top so the other thing that you might want to do is you might want to say home vc.title is now going to be vc.title so instead of actually calling it homevc title what you might want to actually do is call that your primary controller so if i tap on this you'll see it's now the about this app and it's green let's also work on uh the tapping on home so here we'll go ahead and say reset to home and i'll go ahead and create this as a function itself and in here what we basically want to go ahead and do is remove info vc so i'm going to say info vc.view remove from superview we're going to say info vc and we will say did move to parent and pass in nil and we also want to remove a child view controller so let's see is there an info vc remove child i think we actually don't even need a remove child now that i think about it remove child used to exist a long long time ago so i guess we only need to say did it move to that and we should be good but keep in mind we also want to reset the title of home vc to be home so let me go ahead and give this a run and we'll see if everything is working as expected so that's good and once we tap on that that's good as well one thing which is a little questionable if it looks too great is the controller doesn't actually change until the animation is done so it gives a little bit of a delay effect which some people like and some people don't now it's really subjective if you wanted to combat that what you could do is uh ignore this completion handler entirely and pass in nil just like we did up above and you can just go ahead and throw that stuff right there you no longer will need weak self you will still need self dot and what this will do is this will change the controller in parallel to the animation you just need to be careful about the ordering of these events so some people like this a lot better i'm one of those people who thinks this looks a lot nicer but you can go ahead and definitely do this so there you have it that's how you can create a slide out menu from scratch no dependencies the one other thing you might want to add is a tap gesture on the container controller here and if the menu is open when you tap anywhere here it should close whereas right now you have to tap on this item up here the button so that's how you can add some pretty nice navigation this is a very popular pattern as i'm sure most of you are aware of so if you enjoy the video don't forget to drop a like below if you haven't done so already subscribe for more ios and swift related content i've got also my own courses over at iosacademy.io if you like my teaching style take a look at those we have slack channels and it's a pretty engaged community so check it out if you're into it and definitely don't forget to leave a comment down below if you have any questions or video suggestions i always love hearing from you guys thanks again for watching i'll see in the next video
Info
Channel: iOS Academy
Views: 10,097
Rating: undefined out of 5
Keywords: swift side menu from scratch, swift tutorial, side menu ios, swift side menu, swift 5 side menu, swift 5, swift, swift 2021 tutorial, swift basics, swift beginners, swift programming, child view controllers, swiftui side menu, side menu in swift, side menu swift 2021, 2021 swift, how to make side menu swift, swift how to make side menu, side menu swift, how to make side menu in app, swift side menu tutorial, professional side menu, side menu from scratch swift, ios, app
Id: 1hzPFAYcuUI
Channel Id: undefined
Length: 35min 29sec (2129 seconds)
Published: Sat Apr 17 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.