Left side menu (Navigation Drawer) example with Swift

In this video I am going to show you how to create a left side navigation menu which is also some times called “Navigation Drawer”. Navigation drawer is a very popular design pattern used in modern mobile apps and I am sure you have come across so many times.

Navigation drawer is a panel that transitions in from the left edge of the screen and displays the app’s main navigation options. User can bring in left side navigation menu by tapping on the menu button in the left top corner or by swiping from the left edge of the screen.

I am a big fan of code re-use and I like to collect into by developer toolbox, good open source projects which I can quickly re-use in my work to speed up the development process. One of such ready to use open source projects is “MMDrawerController” which can be easily integrated into your iOS app and let you have left & right side navigation menu literally in few minutes.

Let me show you how to do it.

VIDEO #1

Source code I typed in this video:

var window: UIWindow?
var centerContainer: MMDrawerController?func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.var rootViewController = self.window!.rootViewControllerlet mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)

var centerViewController = mainStoryboard.instantiateViewControllerWithIdentifier("ViewController") as ViewController

var leftViewController = mainStoryboard.instantiateViewControllerWithIdentifier("LeftSideViewController") as LeftSideViewController

var rightViewController = mainStoryboard.instantiateViewControllerWithIdentifier("RightSideViewController") as RightSideViewController

var leftSideNav = UINavigationController(rootViewController: leftViewController)
var centerNav = UINavigationController(rootViewController: centerViewController)
var rightNav = UINavigationController(rootViewController: rightViewController)

centerContainer = MMDrawerController(centerViewController: centerNav, leftDrawerViewController: leftSideNav,rightDrawerViewController:rightNav)

centerContainer!.openDrawerGestureModeMask = MMOpenDrawerGestureMode.PanningCenterView;
centerContainer!.closeDrawerGestureModeMask = MMCloseDrawerGestureMode.PanningCenterView;

window!.rootViewController = centerContainer
window!.makeKeyAndVisible()

return true
}

 

VIDEO #2

Source code I typed in this video:

import UIKit

class LeftSideViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

var menuItems:[String] = ["Main","About"];

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(true)
        self.navigationController?.view.layoutSubviews()
    }

override func viewDidLoad() {
super.viewDidLoad()

// Do any additional setup after loading the view.
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return menuItems.count;

}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell

{
var mycell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath) as MyCustomTableViewCell

mycell.menuItemLabel.text = menuItems[indexPath.row]

return mycell;

}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{

switch(indexPath.row)
{

case 0:

var centerViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ViewController") as ViewController

var centerNavController = UINavigationController(rootViewController: centerViewController)

var appDelegate:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate

appDelegate.centerContainer!.centerViewController = centerNavController
appDelegate.centerContainer!.toggleDrawerSide(MMDrawerSide.Left, animated: true, completion: nil)

break;

case 1:

var aboutViewController = self.storyboard?.instantiateViewControllerWithIdentifier("AboutViewController") as AboutViewController

var aboutNavController = UINavigationController(rootViewController: aboutViewController)

var appDelegate:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate

appDelegate.centerContainer!.centerViewController = aboutNavController
appDelegate.centerContainer!.toggleDrawerSide(MMDrawerSide.Left, animated: true, completion: nil)

break;

default:

println("\(menuItems[indexPath.row]) is selected");

}

}

}

 


Learn iOS Development with these Video Courses


How to Make a Freaking iPhone App - iOS 10 and Swift 3
icon icon


iOS 10 & Swift 3: From Beginner to Paid Professional
icon


The Complete iOS 10 Developer Course - Build 21 Apps
icon


Swift 3 - Learn to Code with Apple's New Language
icon icon


Learn How to Build Mobile Apps for iOS with Swift, PHP and MySQL
icon icon

Follow me on one of your favourite social networks to learn about new video tutorials and code examples:

Twitter: @SwiftVideoBlog
Google Plus: https://plus.google.com/+SergeyKargopolov/posts
Facebook: Swift Developer Blog on Facebook



  • Prajyot Kondekar

    I have a question regarding to the navigation bar. I cant change the color of the navigation bar if I use MMDrawerController . Can you guide me?

    • I should work well. Does the colour of the bar changes if the ViewController of your app is not part of NavigationDrawer?

  • Yestay Muratov

    Hello , what should I do if rootcontroller of my app is login page. I dont wanna login page to have sidebarmenu. so how to solve this problem?

    • Yestay, have a look at this video. I think it might be helpful to you: https://youtu.be/Ovb7M4EHMWo

      • Rico

        If I implement this solution the toggle stop to work… Is there any solution?

        • Well, Logout takes user out of Navigation drawer and toggle of course will not work as it is part of NavigationDrawer. I suspect the page you are taking user to is not part of Navigation Drawer, is it?

          • Rico

            No, I mean, if I set navigationDrawer as main view controller, it works well. But if the first controller is another one and the second view is navDrawer, the toggle doesn’t work and I have to open/close the drawer only by swiping. Is it clear?

          • 🙂 no, not very clear… If you set Navigation Drawer as rootViewController then it does not matter whether it is second or third. However if you Push from one view controller to navigation drawer, then behaviour is expected to be different. Yes.

        • I am not sure why your example does not work… Do you think you can share with my your project via github or bitbucket so I could have a look?

          • Rico

            Don’t worry, my fault, I did a mistake, now everything works perfectly, thank you!

          • Awesome!

    • Kofi Bassaw

      Just comment where root view was assigned in the app delegate then assign the root view in your login controller

  • swati

    Hello, how can i connect navigation bar in every view controller?

    • You need to imbed the ViewController you want to have the navigation bar into Navigation Controller

  • Chris Navarro

    Hello there, how can i implement the RightSideButtonTapped, if I’m not getting MMDrawerController implemented in the AppDelegate files, i did it just in the access login button in my login form view (first view when i ask the user to login) ?
    Thank you in advance.

    • SergeyKargopolov

      Chris, does your top left side button work? I am trying to understand your question. You need to add right side button and make it work or both of your top buttons do not work.

  • Htarwara 6245

    First of all,This is wonderful tutorial and so easy for me to learn newbie to swift for me.Thank you.

    When i run MMDrawerController in my xcode project that i download from githud.i found these feature there.
    http://puu.sh/iAvBt/bb8f838cdf.png

    Is there any way i can add animation to my slide in swift?
    Thanks

  • vishal

    Very good Tutorial Thanks …

  • Emil

    Fantastic Tutorial! – thank you very much.

    I have a question though. When i run the app and the first time i open the left menu – using the left toggle button – it makes an “annoying” jump down. If you swipe it open, or if you open the right menu everything looks smooth and nice, but efter a build and run and when you tap left menu button it’s not very smooth. What can you do to fix this.

    Thanks for the great video !

    • snmohanty321

      Hi Emil, Could you please help me . Nothing happens when I click on the < item.

      • sana

        i have same problem..have u find solution??

  • snmohanty321

    Tutorial is so good. But left and right clicks are not working in my case. any idea friends ??????????

    • What error message do you get?

      • snmohanty321

        No errors . only wondering how to connect buttons to the menu. Plz mention the code/ procedure to connect .

    • Also, please check that you have created and Action connector for the right and left side buttons.

      • snmohanty321

        Could you please mention what to create in action connectors ? Thanks in advance.

        • It is when you select the button which is on your ViewController and then hold Control button on your keyboard, drag and drop the connector line to your Swift source code and then change the Connection type to Action, give it a name and save. Unless you create Action connector for your button you will not be able handle its events when the button is tapped.

          • snmohanty321

            Thank you. inside the button connection method need to add some code or it should be blank.

  • snmohanty321

    Do you have any tutorial to fetch wsdl webservice by passing data with ios swift ?Thanks n advance.

    • No, at this moment I do not have any…

      • snmohanty321

        As per your tutorial I think till now it is the best way to connect via url and post method. Can you please say is it possible to fetch wsdl webservice by passing data with ios swift .

  • carlosx2

    I find myself having the problem that i can’t click again on the the slide button when the menu is open. I can swipe to close the menu but i can’t click again on the icon to close the menu. Am i missing something here. I have the same code and everything is working as it should. The button seems to not even accessible when the menu is open. I am using an image is button for this. But it is still a button. It looks like it is being muted.

    • It should be a Bar Button Item. Have you created an Action for it? What is your code inside the action, can you share? The code should simply toggle the left side. There is no other business logic needed there to make it work.

      Sergey

  • carlosx2

    i see that i am not use nav buttons. I will have to fix that. thanks

  • if we have 4 views (except left or right menu) which one is center. Active view must be the center view. How can I do that?

  • Nessim

    I get a Sigabrt error when I set the table view to data source of the left side view controller? What Should I do thanks in advance.

    • It is difficult to tell not seeing an error message. Do you think you can extract some more details from it?

      • Nessim

        Hi, I fixed it. Thank, you. FYI Great tutorial.

        • Awesome!

          • I keep getting the Sigabrt error as well. I have duplicated what you have done and get the following errors:

            var rootViewController = self.window!.rootViewController was never initialized. And I have had to append these two line with an “!” as well:

            var centerViewController = mainStoryboard.instantiateViewControllerWithIdentifier(“WelcomeViewController”) as! WelcomeViewController

            var leftViewController = mainStoryboard.instantiateViewControllerWithIdentifier(“LeftSideViewController”) as! LeftSideViewController

            Can you shed some light on this?

            Thanks
            Andy

          • sana

            assign storyboard id and class to both controller properly.. Check the connections to make sure all your IBOutlets and IBActions are connected correctly and that there aren’t any connections left over from old

          • Gorby Oz

            @sharminmuqadam:disqus Thank you much!! That fix my SIGABRT error.

          • sana

            assign storyboard id and class to both controller properly.. Check the connections to make sure all your IBOutlets and IBActions are connected correctly and that there aren’t any connections left over from old

      • sana

        Side navigation is not showing after completing all steps..can u plz help for that??

  • Mohammed Janish

    I asked this question before, but i could not get the exact result. I need the left side navigation drawer after the login page, not in the main storyboard. What are the changes i need to make in the project?

  • Alessandro Benedetti

    Hi,
    I’ve this error:

    Use of undeclared type ‘MMDrawerController’

    I follow your course on Udemy

  • Hardik Bar

    hello this will work for only one view controller this is not work for other view pls help me … asap

  • Pratama Putra

    Hi,

    Does this example works in swift 2.1? I followed your tutorial, when I declared rootViewController with var rootViewController = self.window!.rootViewController, editor gives me error “initialization variable was never used, replace with assignment to _ or remove it”

    Is there any step that I missed?

    • I will work but you will need to make small changes to make it compatible with Swift 2. Like in this particular example you will need to replace var with let and if you do not use it, then simply remove this line so that Xcode does not complain.

  • Dj Dance

    hmm, did I miss table delegate set in viewDidLoad on video? we need create table IBOutlet and then
    menuItemsTable.delegate=self
    menuItemsTable.dataSource=self

    • You can do that. I have done it when on the main storyboard.

      • Dj Dance

        uhu. So i just missed it on video? please point.. and thanks for lessons!

        • Video #2 fast forward to 14:15. It should be there.

  • adam

    Hello,
    I have followed all your login tutorials and this MMDrawerController tutorial.

    The problem i am getting is the login screen is the main screen and when i go from login to the main view (center) the sidebar button doesnt work. can you please help?

    • Is your login screen part of MMDrawer and is used as a CenterView or it s separate view controller?

      • ROY

        I am having the same problem. My login screen is a separate ViewController

        • Mohammad Tanweer

          My login screen is a separate ViewController. How can I make that part of MMDrawer? Please help

  • rafael rocha

    somebody knows why when I implements the function buildnavigationdrawer in the appdelegate, the drawer works fine, but my navitaionbar dissapear? if somebody could help me? thanks in advance

    • Sirisha Vallabha

      i am also facing same issue. Did you find any solutions?

  • Tak Rahul

    hello sir can you give me this code in objective-c

    • Pankaj Kumar

      Hey Check Objective C codes in comment

    • Pankaj Kumar

      Hey Check Objective C codes in comment

  • Ratnesh Kumar
  • NikitoGR

    @kargopolov:disqus Thank you for the great and well explained tutorial!

    I got 2 questions:

    How can I add icons in every cell, i.e a house on the right of the label menu, an “i” on the right of the label about and show on?

    Is it possible to have a swipe menu inside the central view control, and having only the left sidebar menu?

    • Yes, all of it is possible. I do not have any example though to share at this moment…

    • Yes, all of it is possible. I do not have any example though to share at this moment…

  • Robert Kuzma

    Hi. thanks for the great tutorial.

    I am trying to create a 2 level navigation. The main navigation icons would be placed on the “home screen”. A bunch of icons you can click on and it takes you deeper in the app.
    The secondary navigation would be in the drawer: I would have there the navigation that is not used so ofter: Settings, language selection, login information …
    Does this makes sense or am I off?
    How to start working on it? Do I need 2 navigation controllers?

  • Striker Uyghur

    Hi, Great tutorial, I wanted to add firebase login to app launch.can you help for that ?

  • sana

    Side navigation is not showing after completing all steps..can u plz help for that??

  • sana

    now its working.. thanks for the great tutorial.

  • Farid Andres Diaz Ruilova

    My login screen is a separate ViewController…What to do?

    • sana

      if your login is first screen then assign login view controller as a root controller in Appdelegate.swift file..and navigation bar make it hidden in login view controller..and the call view controller in which you want navigation bar in the following way

      let NavigateViewController = self.storyboard?.instantiateViewControllerWithIdentifier(“NavigationViewController”) as! NavigationViewController
      let NavController = UINavigationController(rootViewController: NavigateViewController)
      let appDelegate:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
      appDelegate.centerContainer!.centerViewController = NavController

  • Farid Andres Diaz Ruilova

    My login screen is a separate ViewController…What to do?

  • nasi

    i have two initial view controller. one login page and one home page. i managed to get mmdrawer controller working from home page. but my problem is that when the user first uses log in page, and then goes to the home page, he can’t use the mmdrawer controller. i think it’s because i put th whole code in the app did finish lunching method. and when the user goes to the home “from the login page” i kind of loose contact with that method. any idea how to fix this?

    this is my code :
    self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
    let mainStoryboard: UIStoryboard = UIStoryboard(name: “Main”, bundle: nil)

    let defaults = NSUserDefaults.standardUserDefaults()

    var id = defaults.stringForKey(“customerid”)

    let exampleViewController: UINavigationController = mainStoryboard.instantiateViewControllerWithIdentifier(“mainNav”) as! UINavigationController
    if id != nil {

    var centerViewController = mainStoryboard.instantiateViewControllerWithIdentifier(“displayCategory”) as! Category

    var leftViewController = mainStoryboard.instantiateViewControllerWithIdentifier(“LeftSideViewController”) as! LeftSideViewController
    self.window?.rootViewController = exampleViewController

    self.window?.makeKeyAndVisible()
    var rootViewController = self.window!.rootViewController

    var leftSideNav = UINavigationController(rootViewController: leftViewController)
    var centerNav = UINavigationController(rootViewController: centerViewController)

    centerContainer = MMDrawerController(centerViewController: centerNav, leftDrawerViewController: leftSideNav)

    centerContainer!.openDrawerGestureModeMask = MMOpenDrawerGestureMode.PanningCenterView
    centerContainer!.closeDrawerGestureModeMask = MMCloseDrawerGestureMode.PanningCenterView

    window!.rootViewController = centerContainer

    }
    else {

    var exampleViewController: SignupViewController = mainStoryboard.instantiateViewControllerWithIdentifier(“signup”) as! SignupViewController

    self.window?.rootViewController = exampleViewController

    self.window?.makeKeyAndVisible()

    }

  • Sam

    How to solve those errors please?

    • Sam, these are not errors but recommendations to change “var” to “let”. If you rename “var” to “let” the recommendation in yellow will go away.

      • Sam

        should i accept the recommendation from to”var” to “let”?
        why i did not appear in your video, as i follow all your line coding ?
        where i can add the same Bar in the attached image on the left?

        • Yes, Sam. Accept recommendations. This is because when I was recording this video it was Swift 1 and then Apple updated it to Swift 2 and then to Swift 3. If you accept recommendations from Xcode, you should be able to get Swift 3 version eventually. Also, check out this page with Swift 3 code snippets. Some of them might be very helpful to you: swiftdeveloperblog.com/code-examples

          • Sam

            Hi kargopolov
            such long time we did not hear from u, could u make a tutorial about
            the animation for a photos of gallery , also about twirl for transition all in swift 3 please

      • Sam

        i just ve implemented it , i can not see center,right,or left page which was already created?

  • Sam

    How to solve those errors please?

  • Pankaj Kumar

    For Objective C
    —- AppDelegate Implementation——
    @implementation AppDelegate

    – (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    UIStoryboard *mainStoryBorad = [UIStoryboard storyboardWithName:@”Main” bundle:nil];

    UIViewController *leftView = [mainStoryBorad instantiateViewControllerWithIdentifier:@”LeftDrawerViewController”];

    UIViewController *centerView = [mainStoryBorad instantiateViewControllerWithIdentifier:@”MainViewController”];

    UINavigationController *leftNav =[[UINavigationController alloc]initWithRootViewController:leftView];

    UINavigationController *centerNav = [[UINavigationController alloc]initWithRootViewController:centerView];

    self.drawerController = [[MMDrawerController alloc]initWithCenterViewController:centerNav leftDrawerViewController:leftNav];

    self.drawerController.openDrawerGestureModeMask = MMOpenDrawerGestureModePanningCenterView;

    self.drawerController.closeDrawerGestureModeMask = MMCloseDrawerGestureModePanningCenterView;

    _window.rootViewController = self.drawerController;

    [_window makeKeyAndVisible];

    // Override point for customization after application launch.

    return YES;

    }

    ——————————————————
    tableView Select Action
    ——————————————————

    – (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

    switch(indexPath.row)

    {

    case 0:{

    UIViewController *centerViewController = [self.storyboard instantiateViewControllerWithIdentifier:@”MainViewController”];

    UINavigationController *centerNavController = [[UINavigationController alloc]initWithRootViewController:centerViewController] ;

    AppDelegate *app = [[UIApplication sharedApplication]delegate];

    app.drawerController.centerViewController = centerNavController;

    [app.drawerController toggleDrawerSide:MMDrawerSideLeft animated:YES completion:nil];

    }

    break;

    case 1:{

    UIViewController *centerViewController = [self.storyboard instantiateViewControllerWithIdentifier:@”SecondViewController”];

    UINavigationController *centerNavController = [[UINavigationController alloc]initWithRootViewController:centerViewController] ;

    AppDelegate *app = [[UIApplication sharedApplication]delegate];

    app.drawerController.centerViewController = centerNavController;

    [app.drawerController toggleDrawerSide:MMDrawerSideLeft animated:YES completion:nil];

    }
    break;

    default:

    NSLog(@”%ld is selected”,(long)indexPath.row);
    }

    }

  • Pankaj Kumar

    For Objective C
    —- AppDelegate Implementation——
    @implementation AppDelegate

    – (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    UIStoryboard *mainStoryBorad = [UIStoryboard storyboardWithName:@”Main” bundle:nil];

    UIViewController *leftView = [mainStoryBorad instantiateViewControllerWithIdentifier:@”LeftDrawerViewController”];

    UIViewController *centerView = [mainStoryBorad instantiateViewControllerWithIdentifier:@”MainViewController”];

    UINavigationController *leftNav =[[UINavigationController alloc]initWithRootViewController:leftView];

    UINavigationController *centerNav = [[UINavigationController alloc]initWithRootViewController:centerView];

    self.drawerController = [[MMDrawerController alloc]initWithCenterViewController:centerNav leftDrawerViewController:leftNav];

    self.drawerController.openDrawerGestureModeMask = MMOpenDrawerGestureModePanningCenterView;

    self.drawerController.closeDrawerGestureModeMask = MMCloseDrawerGestureModePanningCenterView;

    _window.rootViewController = self.drawerController;

    [_window makeKeyAndVisible];

    // Override point for customization after application launch.

    return YES;

    }

    ——————————————————
    tableView Select Action
    ——————————————————

    – (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

    switch(indexPath.row)

    {

    case 0:{

    UIViewController *centerViewController = [self.storyboard instantiateViewControllerWithIdentifier:@”MainViewController”];

    UINavigationController *centerNavController = [[UINavigationController alloc]initWithRootViewController:centerViewController] ;

    AppDelegate *app = [[UIApplication sharedApplication]delegate];

    app.drawerController.centerViewController = centerNavController;

    [app.drawerController toggleDrawerSide:MMDrawerSideLeft animated:YES completion:nil];

    }

    break;

    case 1:{

    UIViewController *centerViewController = [self.storyboard instantiateViewControllerWithIdentifier:@”SecondViewController”];

    UINavigationController *centerNavController = [[UINavigationController alloc]initWithRootViewController:centerViewController] ;

    AppDelegate *app = [[UIApplication sharedApplication]delegate];

    app.drawerController.centerViewController = centerNavController;

    [app.drawerController toggleDrawerSide:MMDrawerSideLeft animated:YES completion:nil];

    }
    break;

    default:

    NSLog(@”%ld is selected”,(long)indexPath.row);
    }

    }

  • Lyheang IBell

    How can I use with UITableViewCellContentView ? it does not work for me

  • Eddie Ma

    Hi,
    Thanks for your tutorial.
    I followed your video to do a left drawer layout. But I got a problem. my centerViewControllor has a Web view to display a video, and every time I clicked table in leftViewController to go back to my centerViewController. The response time is quite long. I do not know what is wrong with that. Can you give me sone hints?

    Thanks