Tip: Creating Navigation Controllers

iOS Development tips weekly is a series you can find at the Lynda.com and LinkedIn Learning libraries. The first week of a week’s tip will be available to the public. After that, you will need a subscription to get access to it. Click the image the left  to view.  You’ll find a transcript below.

Not everyone loves the Storyboard. With playgrounds, you can’t use the storyboard. Often storyboards make for less portable code. Making user interfaces in code solves all these problems. If you do, you may need navigation controllers in code. Let me show how to create navigation controllers both in playgrounds, and in an Xcode project.

In the downloads examples file, I embedded a playground into an Xcode project so we can look at both projects and playgrounds. Open it up.  It’s two view controllers, yellow and blue, connected through a bar button item.

In the action of the bar button item, I’ll make some code to navigate from the yellow controller to the blue controller. I’ll first add an instance of the controller

let bvc = BlueViewController()

and then use the pushViewController method to show the Blue view controller.

navigationController?.pushViewController(bvc, animated: true)

Launching  a view controller is that easy, but you need to set up the navigation controller too. There’s only a few steps to make navigation controllers. The first step is to create the root view controller. This will be the controller we start the app with. I’ll set the YellowViewController as a root view controller.

let rootViewController = YellowViewController()

Once I have a root view controller, I can make a navigation controller, with the root controller.

let navigationController = UINavigationController(rootViewController: rootViewController)

And then just assign it as the live view.

PlaygroundPage.current.liveView = navigationContro

Run this and you get a navigation controller you can navigate between the  view controllers.

  

You can do this to a Xcode project too, but it’s slightly more work.  In the Xcode project proper, you’ll see I made the same yellow controller, and expanded blue to go to a red controller I added to the project.  I’ll come back to red shortly,  but first let’s create the navigation controller.

You make the navigation controller in the AppDelegate in the application:DidFinishLaunchingWithOptions: method. The first two steps are the same as the playground. Make a root view controller, and make a navigation controller from the root controller.

let rootViewController = YellowViewController()
let navigationController = UINavigationController(rootViewController: rootViewController)

You’ll notice the top of the Appdelegate the var window. Instead of the current playground page’s live view, you’ll assign the navigation controller to the window’s rootViewController property.

window?.rootViewController = navigationController

While this should be the first window to open, many developers get a little paranoid and make sure it is the top active window with the makeKeyAndVisible method.

window?.makeKeyAndVisible()

Run this and you’ll get the yellow controller.

Tap Blue and you get the blue.

Tap red and you get the red .

You’ll see a bar button on Red called Root. It does nothing now, but I want to show you how to dismiss the controller without using the back button.

Stop the app. Go to the red view controller code. Navigation controllers are stacks, so if you push a controller to present it, you pop it off the stack to remove it. In the root function,  add this:

navigationController?.pop

You see three choices in the autocomplete.

If you want to pop back to the last controller, you use popViewController. For a controller farther down the stack you use popToViewController. If you want to go all the way back to the root controller you use  PopToRootController, which is what I’ll use, and set animated to true.

navigationController?.popToRootViewController(animated: true)

Run this. Go to the red controller.

Tap Root. You go back to yellow.

With push, pop, the navigation controller object and no storyboard, you can do everything you’d possibly want with navigation controller. With only the difference between the playground page’s live view and the App delegate’s  window, it’s very easy to port navigation controller code between Playgrounds and Xcode projects.

The whole code

You can find the completed project on gitHub here

.playground

import UIKit 
import PlaygroundSupport

class BlueViewController:UIViewController{
    override func viewDidLoad(){
    super.viewDidLoad()
    view.backgroundColor = .blue
        title = "Blue"
    }
}

class YellowViewController:UIViewController{
    @IBAction func blue(selection:UIBarButtonItem){
    let bvc = BlueViewController()
        navigationController?.pushViewController(bvc, animated: true)
    }
    
    override func viewDidLoad(){
        super.viewDidLoad()
        let blueItem = UIBarButtonItem(title: "Blue", style: .plain, target: self, action: #selector(blue))
        navigationItem.rightBarButtonItem = blueItem
        view.backgroundColor = .yellow
        title = "Yellow"
    }
}

let rootViewController = YellowViewController()
let navigationController = UINavigationController(rootViewController: rootViewController)
PlaygroundPage.current.liveView = navigationController

AppDelegate.swift

//
//  AppDelegate.swift
//  NavigationController
//
//  Created by Steven Lipton on 12/5/17.
//  Copyright © 2017 Steven Lipton. All rights reserved.
//

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        let rootViewController = YellowViewController()
        let navigationController = UINavigationController(rootViewController: rootViewController)
        window?.rootViewController = navigationController
        window?.makeKeyAndVisible()
        
        
        
        
        return true
    }
// For brevity, I've left off the default methods here. Assume they exist below this comment. 
}

YellowViewController.swift

//
//  YellowViewController.swift
//  Tips_09_NavigationController_Begin
//
//  Created by Steven Lipton on 12/4/17.
//  Copyright © 2017 Steven Lipton. All rights reserved.
//

import UIKit

class YellowViewController: UIViewController {

   
    @IBAction func blue(selection:UIBarButtonItem){
        let bvc = BlueViewController()
        navigationController?.pushViewController(bvc, animated: true)
    }
    
    override func viewDidLoad(){
        super.viewDidLoad()
        let blueItem = UIBarButtonItem(title: "Blue", style: .plain, target: self, action: #selector(blue))
        navigationItem.rightBarButtonItem = blueItem
        view.backgroundColor = .yellow
        title = "Yellow"
    }
}

BlueViewController.swift

//
//  BlueViewController.swift
//  Tips_09_NavigationController_Begin
//
//  Created by Steven Lipton on 12/4/17.
//  Copyright © 2017 Steven Lipton. All rights reserved.
//

import UIKit

class BlueViewController: UIViewController {
    @IBAction func red(selection:UIBarButtonItem){
        let bvc = RedViewController()
        navigationController?.pushViewController(bvc, animated: true)
    }
    
    override func viewDidLoad(){
        super.viewDidLoad()
        let redItem = UIBarButtonItem(title: "Red", style: .plain, target: self, action: #selector(red))
        navigationItem.rightBarButtonItem = redItem
        view.backgroundColor = .blue
        title = "Blue"
    }
}

RedViewController.swift

//
//  RedViewController.swift
//  Tips_09_NavigationController_Begin
//
//  Created by Steven Lipton on 12/4/17.
//  Copyright © 2017 Steven Lipton. All rights reserved.
//

import UIKit

class RedViewController: UIViewController {

    @IBAction func root(selection:UIBarButtonItem){
       navigationController?.popToRootViewController(animated: true)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let rootItem = UIBarButtonItem(title: "Root", style: .plain, target: self, action: #selector(root))
        navigationItem.rightBarButtonItem = rootItem
        view.backgroundColor = .red
        title = "Red"
    }

}

One Reply to “Tip: Creating Navigation Controllers”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.