Pop 2 view controllers in Nav Controller in Swift
IosUinavigationcontrollerIos Problem Overview
I have found many ways to pop back 2 UIViewControllers
in UINavigationController
using Objective-C, however when I try and switch that over to Swift it doesn't seem to be working.
What would be the best approach to pop back to UIViewController
?
Any guidance would be appreciated
Thanks
Ios Solutions
Solution 1 - Ios
Expanding on my comment, find the second last view controller in the viewControllers array and then use popToViewController to avoid overwriting the entire view controller stack.
Example (assumes the navigation controller has more than 1 view controller):
func backTwo() {
let viewControllers: [UIViewController] = self.navigationController!.viewControllers as [UIViewController]
self.navigationController!.popToViewController(viewControllers[viewControllers.count - 3], animated: true)
}
Objective-C
NSArray *viewControllers = [self.navigationController viewControllers];
[self.navigationController popToViewController:viewControllers[viewControllers.count - 3] animated:YES];
Solution 2 - Ios
I wrote an UIViewController extension (Swift 3+ ready)
You could use like this :
/// pop back n viewcontroller
func popBack(_ nb: Int) {
if let viewControllers: [UIViewController] = self.navigationController?.viewControllers {
guard viewControllers.count < nb else {
self.navigationController?.popToViewController(viewControllers[viewControllers.count - nb], animated: true)
return
}
}
}
Usage :
self.popBack(3)
Bonus dismiss to a specific viewcontroller
/// pop back to specific viewcontroller
func popBack<T: UIViewController>(toControllerType: T.Type) {
if var viewControllers: [UIViewController] = self.navigationController?.viewControllers {
viewControllers = viewControllers.reversed()
for currentViewController in viewControllers {
if currentViewController .isKind(of: toControllerType) {
self.navigationController?.popToViewController(currentViewController, animated: true)
break
}
}
}
}
Usage :
self.popBack(toControllerType: MyViewController.self)
Solution 3 - Ios
user5320485 answer in swift3
let viewControllers = self.navigationController!.viewControllers as [UIViewController];
for aViewController:UIViewController in viewControllers {
if aViewController.isKind(of: AdCreateViewController.self) {
_ = self.navigationController?.popToViewController(aViewController, animated: true)
}
}
Solution 4 - Ios
You can dynamically pop multiple viewcontrollers in (swift 2.0)
let allViewController: [UIViewController] = self.navigationController!.viewControllers as [UIViewController];
for aviewcontroller : UIViewController in allViewController
{
if aviewcontroller .isKindOfClass(YourDestinationViewControllerName)
{
self.navigationController?.popToViewController(aviewcontroller, animated: true)
}
}
Solution 5 - Ios
Swift 4 UINavigationController extension version of @Maximelc's answer:
extension UINavigationController {
func popBack(_ nb: Int) {
let viewControllers: [UIViewController] = self.viewControllers
guard viewControllers.count < nb else {
self.popToViewController(viewControllers[viewControllers.count - nb], animated: true)
return
}
}
/// pop back to specific viewcontroller
func popBack<T: UIViewController>(toControllerType: T.Type) {
var viewControllers: [UIViewController] = self.viewControllers
viewControllers = viewControllers.reversed()
for currentViewController in viewControllers {
if currentViewController .isKind(of: toControllerType) {
self.popToViewController(currentViewController, animated: true)
break
}
}
}
}
Solution 6 - Ios
Here is another, slightly "fool-proof" version:
extension UINavigationController {
func popBack(_ count: Int) {
guard count > 0 else {
return assertionFailure("Count can not be a negative value.")
}
let index = viewControllers.count - count - 1
guard index > 0 else {
return assertionFailure("Not enough View Controllers on the navigation stack.")
}
popToViewController(viewControllers[index], animated: true)
}
}
Solution 7 - Ios
If you want to pop on a specific view controller you can search that view controller by replacing DestinationViewController with your view controller in sample code.
func moveToDestinationViewController() {
let viewController = self.navigationController?.viewControllers.first { $0 is DestinationViewController }
guard let destinationVC = viewController else { return }
self.navigationController?.popToViewController(destinationVC, animated: true)
}
Solution 8 - Ios
I did a helper to make it easy:
import Foundation
import UIKit
class NavigationHelper {
static func back(number: Int, from viewControlller : UIViewController) {
let viewsBack = number + 1
let viewControllers: [UIViewController] = viewControlller.navigationController!.viewControllers as [UIViewController]
viewControlller.navigationController!.popToViewController(viewControllers[viewControllers.count - viewsBack], animated: true)
}
static func back(number: Int, from viewControlller: UITableViewController) {
let viewsBack = number + 1
let viewControllers: [UIViewController] = viewControlller.navigationController!.viewControllers as [UIViewController]
viewControlller.navigationController!.popToViewController(viewControllers[viewControllers.count - viewsBack], animated: true)
}
}
For example, in your ViewController
you can use NavigationHelper.back(number: 1, from: self)
Solution 9 - Ios
let allViewControllers : [UIViewController] = self.navigationController!.viewControllers as [UIViewController]
self.navigationController?.popToViewController(allViewControllers[allViewControllers.count-3], animated: true)