【问题标题】:Specifying behaviour of a Back button per view controller为每个视图控制器指定后退按钮的行为
【发布时间】:2016-08-15 11:40:03
【问题描述】:

我有几个视图控制器,分别称为 1、2、3、4、5 和 6。我创建了一个 UINavigationController,它有一个后退按钮。后退按钮出现在每个视图控制器上(我从不隐藏它)。

现在我有这样的情况。我从 1,2,3,4,5 然后回到 3。作为附加信息,从 5 到 3 的转换是使用手动 segue 完成的(但有时我使用其他 segue,如 push 或 modal)。如果我点击该视图控制器上的后退按钮,通常它会转到 5,因为堆叠是如何工作的。但是我希望能够从视图控制器 3 中指定,当点击后退按钮时,您总是会转到 vc 2...

我想在这里操作导航堆栈可能是一种方法(基于当前视图控制器),但我不知道这是理想的,还是有更合适的...

【问题讨论】:

    标签: ios swift uinavigationcontroller segue


    【解决方案1】:

    您可以继承并覆盖UINavigationController 中的一些方法,以便在按下后退按钮时获得回调。然后你可以强制导航控制器以你想要的方式响应。

    例如,当调用popViewController(animated:) 时,您可以根据视图控制器(或您想要的任何方式)确定您是否应该实际允许正常的后退按钮功能。如果您想要正常行为,只需致电super。在从视图控制器 3 转到视图控制器 2(而不是视图控制器 5)的情况下,您不会调用 super,而是调用 popToViewController(viewController2, animated: animated)

    【讨论】:

    • 我最终这样做了......尝试了其他一些方法,但这是最简单和最干净的实施方式。至少对我来说。
    • 我刚刚注意到控制台中有一条警告,上面写着:在意外状态下完成导航转换。导航栏子视图树可能会损坏。 如果我执行 popToViewController(vc2, animated:animated),就会发生这种情况。如果我将动画设置为 false,则消息会消失,但后退按钮也会消失。我想这是某种竞争条件。知道如何在不丢失后退按钮的情况下摆脱此消息吗?
    【解决方案2】:

    通常,当我想“跳”回多个视图时,我会使用“委托”。你真正想做的是从堆栈中弹出几个,而不仅仅是继续你想去的地方。

    我推荐的是每个通过的 VC 上的委托方法。即 VC 1 可以关闭 VC 2,VC 2 可以关闭 VC 3 等。然后,当您在 VC 5 上时,您调用 navigateToView(index: Int) 进行快速检查,如果他们查看响应该委托调用的控制器与该索引匹配然后你只需弹出以前显示的 VC,你就很好了。如果不是,则弹出先前显示的 VC,然后调用该 VC 委托方法,直到到达您想要的位置。

    一种常见的设计模式是负责显示另一个 VC 的 VC,它决定是否应该关闭它。这也让您可以灵活地根据需要在返回之前的视图之前更新 UI。

    希望这有一定的意义并有所帮助。

    【讨论】:

      【解决方案3】:

      用您自己的自定义按钮替换后退按钮,您可以将操作设置为执行转回 3。或者您可以使用导航控制器子堆栈返回 3,无论您喜欢哪个。

      在视图控制器中添加以下代码:

      let backButton: UIBarButtonItem = UIBarButtonItem(title: "Back", style: .plain, target: self, action: #selector(viewController.navigationController?.popViewController(animated:)))
      
          viewController.navigationItem.setLeftBarButton(backButton, animated: true)
      

      目前该操作将使用默认行为并弹回一个。但是,您可以使用自己的方法更改此设置并执行回 3。

      【讨论】:

      • 我刚刚删除了我的评论,因为它无关紧要。我误解了你所说的 segue 的意思,所以我现在明白你在说什么了。
      【解决方案4】:

      假设您打开了 VC 的 1、2、3、4、5。 比你打开VC 3。 所以你有这样的UINavigationControllercontrollers stack [1, 2, 3, 4, 5, 3]

      如果您想返回到 UIViewController #3 的转换,您可以在转换完成 #3 时移除控制器 #3、#4 和 #5(从导航堆栈的中间)。

      func viewDidLoad() {
             self.navigationController.delegate = self
      }
      
      func navigationController(navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
      
          NSMutableArray *allViewControllers = [NSMutableArray arrayWithArray: navigationController.viewControllers];
      //Navigation stack now is [1, 2, 3, 4, 5, 3]. removing VC #3
              [allViewControllers removeObjectAtIndex: 2];
      
      //Navigation stack now is [1, 2, 4, 5, 3]. removing VC #4
              [allViewControllers removeObjectAtIndex: 2];
      
      //Navigation stack now is [1, 2, 5, 3].removing VC #5
              [allViewControllers removeObjectAtIndex: 2];
      
      //Navigation stack now is [1, 2, 3]
      navigationController.viewControllers = allViewControllers;
      
      }
      

      从导航堆栈中删除视图控制器后,您将返回从 3 到 2 的过渡

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-30
        相关资源
        最近更新 更多