Xcode 7.2.1
iOS 9.2
Swift 2.1.1
OSX 10.10.5
The following worked for me:
You can use navigationController?.popViewControllerAnimated(true)
in a loop to go skip as many view controllers as you want.
If the ViewController that you want to go back to is the first ViewController in the UINavigationController stack, you can use navigationController?.popToRootViewControllerAnimated(true)
to go back to the first view controller.
The app still animates through the skipped ViewController, so you see the skipped View slide by on the way to the target ViewController.
I have attempted using:
self.navigationController?.viewControllers.removeLast(), within the
segue between the List of friends to select chatting to remove it
from the stack. But then after the navigating to Show chat with
friend, the back button disappears...
Hmmm...that seems like it should work. The back button information is retrieved from the previous ViewController's navigationItem
property. The previous ViewController's navigationItem.backBarButtonItem
contains the information for the back button that you see. So, when you removed that ViewController from the stack, why didn't the UINavigationController retrieve the navigationItem.backBarButtonItem
info from an earlier ViewController?
It sounds like the destination ViewController may have already gotten ahold of a weak reference to the previous ViewController--the one you removed from the stack. Then, when you removed the previous ViewController from the viewControllers array, the previous ViewController disappeared, and the weak reference was assigned nil--which prevented the destination ViewController from getting the information for the back button; hence no back button was displayed.
AppDelegate.swift:
//
// AppDelegate.swift
// NavigationBarExample
//
// Copyright © 2016 7stud. All rights reserved.
//
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
let navController = window!.rootViewController as! UINavigationController
let friendsController = navController.topViewController as! FriendsTableViewController
friendsController.friendStore = FriendStore(names: ["Joe", "Cathy", "Bobo"])
return true
}
...
...
FriendsTableViewController.swift:
// FriendsTableViewController.swift
// NavigationBarExample
//
//
// Copyright © 2016 7stud. All rights reserved.
//
import UIKit
class FriendsTableViewController: UITableViewController {
var friendStore: FriendStore!
override func viewDidLoad() {
super.viewDidLoad()
//Prevent TableView from underlapping the status bar:
let statusBarHeight = UIApplication.sharedApplication().statusBarFrame.height
let insets = UIEdgeInsets(
top: statusBarHeight, left: 0, bottom: 0, right: 0
)
tableView.contentInset = insets
tableView.scrollIndicatorInsets = insets
}
//MARK: - UITableViewDataSource methods:
override func tableView(tableView: UITableView,
numberOfRowsInSection section: Int)
-> Int
{
return friendStore.allFriends.count
}
override func tableView(tableView: UITableView,
cellForRowAtIndexPath
indexPath: NSIndexPath)
-> UITableViewCell
{
let friend = friendStore.allFriends[indexPath.row]
let cell = tableView.dequeueReusableCellWithIdentifier(
"UITableViewCell-Default",
forIndexPath: indexPath
)
cell.textLabel?.text = friend.name
return cell
}
//MARK: - Segue:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ShowFriend" {
if let row = tableView.indexPathForSelectedRow?.row {
let viewController2 = segue.destinationViewController as! ViewController2
viewController2.friend = friendStore.allFriends[row]
viewController2.previousTitle = navigationItem.title
}
}
}
}
FriendStore.swift:
//
// FriendStore.swift
// NavigationBarExample
//
// Copyright © 2016 7stud. All rights reserved.
//
import Foundation
class FriendStore {
var allFriends: [Friend] = []
init(names: [String]) {
for name in names {
allFriends.append(Friend(name: name) )
}
}
}
Friend.swift:
//
// Friend.swift
// NavigationBarExample
//
// Copyright © 2016 7stud. All rights reserved.
//
import Foundation
class Friend: NSObject {
var name: String
init(name: String) {
self.name = name
super.init()
}
}
ViewController2.swift:
//
// ViewController2.swift
// NavigationBarExample
//
// Copyright © 2016 7stud. All rights reserved.
//
import UIKit
class ViewController2: UIViewController {
var friend: Friend! {
didSet {
navigationItem.title = friend.name
}
}
var previousTitle: String!
override func viewDidLoad() {
//Set the correct title for the back button on the next view controller:
let myBackButtonItem = UIBarButtonItem(
title: previousTitle,
style: .Plain,
target: nil,
action: nil //An action specified here won't get called--I
//think the NavigationController must overwrite this sometime later.
)
navigationItem.backBarButtonItem = myBackButtonItem
}
}
ViewController3.swift:
//
// ViewController3.swift
// NavigationBarExample
//
// Copyright © 2016 7stud. All rights reserved.
//
import UIKit
class ViewController3: UIViewController {
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
let goBackCount = 2
if let navController = navigationController {
let viewControllers = navController.viewControllers
if viewControllers.count >= goBackCount {
for _ in 1...goBackCount {
navController.popViewControllerAnimated(true)
}
}
}
}
}
A less general way to accomplish the same thing is: if the controller you want to go back to is the root ViewController, i.e. it's the first controller in the UINavigationController stack, then in viewWillDisappear()
you can simply call navigationController?.popToRootViewControllerAnimated(true)
Main.storyboard:
After I created the Table View
in the storyboard, I selected the Table View
and in the Xcode menu bar, I selected Editor>Embed In>NavigationController
. The Navigation Controller
is the initial view controller
. I also double clicked on the middle of the navigation bar in the Table View
and set the title to Friends
.
Then I control+dragged from the Prototype Cell
in the Table View
to View Controller2
; from the popup I chose Selection Segue->Show
.
Then I control+dragged from the button in View Controller2
to View Controller3
; from the popup I chose Action Segue->Show
.