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" } }
Leave a Reply