38

我的应用程序的主页有UIButtons,btnIncomebtnExpense. 按下此按钮分别按下IncomeVC和按下ExpenseVC,这是UIViewControllers通过UITabBarxib 添加的两个。tabBar 有 4 个项目。在每个选项卡项目上选择添加相同的四个视图控制器(其中包含UITableViews)作为和的子视图,IncomeVC例如ExpenseVCDailyVC、WeeklyVC、MonthlyVC、YearlyVC。(即,对于收入,有每日、每周等,对于费用也是如此)(我这样做是因为IncomeVCandExpenseVC有 aUIButton和 aUIView这对于所有选项卡都是通用的)。

所以问题是,如果点击btnIncome我必须用与收入相关的数组填充这些表格视图,反之亦然。如何从哪个 viewController 中找到我选择了不同的选项卡(我需要从我添加为 IncomeVC 和 ExpenseVC 的子视图的 4 个视图中获取它)。我是否必须为收入和费用分别制作 8 个不同的视图 4?谢谢。

4

11 回答 11

38

Swift 3中,

if let navController = self.navigationController, navController.viewControllers.count >= 2 {
     let viewController = navController.viewControllers[navController.viewControllers.count - 2]
}
于 2016-10-18T05:19:04.020 回答
37

您可以像下面的代码一样获取以前的 viewController,

NSLog(@"%@",[self.navigationController.viewControllers objectAtIndex:self.navigationController.viewControllers.count-2]);

这将显示以前的 viewController 名称...

于 2013-05-17T12:22:32.070 回答
20

斯威夫特

let n: Int! = self.navigationController?.viewControllers?.count
let myUIViewController = self.navigationController?.viewControllers[n-2] as! UIViewController
于 2014-12-04T15:04:41.120 回答
13

斯威夫特 3

这是可以放入扩展中的先前答案的混搭:

extension UIViewController{
   var previousViewController:UIViewController?{
        if let controllersOnNavStack = self.navigationController?.viewControllers, controllersOnNavStack.count >= 2 {
            let n = controllersOnNavStack.count
            return controllersOnNavStack[n - 2]
        }
        return nil
    }
}

编辑:

在获取previousViewController给定视图控制器的 VC1 时,将其称为 VC1,其中viewWillDisappearVC1 已经从导航控制器堆栈中弹出。所以在这种情况下,上面的代码最终并没有直接获取 VC1 上方的视图控制器(称为 VC2),而是获取 VC2 上方的视图控制器(如果存在)。

previousViewController为了避免这个问题,我只检查 VC1 在请求时是否仍在堆栈上。这是更新的代码:

extension UIViewController{
    var previousViewController:UIViewController?{
        if let controllersOnNavStack = self.navigationController?.viewControllers{
            let n = controllersOnNavStack.count
            //if self is still on Navigation stack
            if controllersOnNavStack.last === self, n > 1{
                return controllersOnNavStack[n - 2]
            }else if n > 0{
                return controllersOnNavStack[n - 1]
            }
        }
        return nil
    }
}

此代码假定您发送previousViewController消息的视图控制器将位于导航堆栈的顶部或根本不在。

于 2017-03-21T01:17:06.257 回答
11

斯威夫特 5.1

(基于以前的答案,但更简单)

extension UINavigationController {
    var previousViewController: UIViewController? {
       viewControllers.count > 1 ? viewControllers[viewControllers.count - 2] : nil
    }
}
于 2019-11-04T17:41:21.990 回答
10

如果需要访问前一个视图控制器的原因是知道要获取什么数据,我建议您在将数据推送到堆栈之前将数据提供给新的视图控制器。或者至少有足够的数据,以便视图控制器知道如何获取正确的数据,例如枚举或常量或其他东西。

这可以通过自定义初始化程序或属性来完成。看看这篇博文的例子:“在视图控制器之间传递数据”

如果您使用的是故事板,则可以使用它prepareForSegue:sender来传递正确的数据。一个很好的教程可以在这里找到:在 iOS 5 第 2 部分中开始故事板

于 2013-05-29T09:52:10.010 回答
4
UIViewController *previousViewController = [[[self navigationController]viewControllers] objectAtIndex:([viewControllers indexOfObject:self]-1)];

self 将是当前视图控制器。

于 2014-01-23T11:21:57.650 回答
2

迅速

extension UINavigationController {
    func getPreviousViewController() -> UIViewController? {
        let count = viewControllers.count
        guard count > 1 else { return nil }
        return viewControllers[count - 2]
    }
}
于 2018-06-07T15:43:32.140 回答
0

您当然可以重用视图控制器。我建议不要在按下按钮时推送 UIViewController(其中包含从 IB 添加的 UITabBar),而是可以推送包含 4 个视图控制器(每日、每周、每月和每年)的 UITabBarController。

您的 UITabBarController 可以有一个枚举属性(收入和费用),并且可以在您根据按下的按钮按下此 UITabBarController 时分配它。从那里,您可以将另一个枚举属性(收入和费用)分配给 4 个 UIViewController,以在每个视图控制器中显示正确的数据类型。

于 2013-05-29T09:27:45.913 回答
0

查看这篇文章:如何在导航堆栈中识别先前的视图控制器 Tony 是对的,您可以从 viewControllers 数组中获取先前的 VC,但索引为 n-2。

于 2013-05-29T09:43:17.203 回答
0

这里的所有答案都实现了[viewControllers.count - 2]方法,但它返回最后一个视图控制器的前一个控制器没有说明!如果声明的视图控制器不是导航堆栈的最后一个视图控制器[viewControllers.count - 2],则返回不正确的结果。

新解决方案:

迅速

extension UIViewController {

    var previousViewController: UIViewController? {
        guard let viewControllers = navigationController?.viewControllers,
              let index = viewControllers.index(of: self),
              index > 0
        else { return nil }
        
        return viewControllers[index - 1]
    }
}
于 2021-07-12T11:39:14.227 回答