我在从导航堆栈中删除 ViewController 时遇到问题?

Posted

技术标签:

【中文标题】我在从导航堆栈中删除 ViewController 时遇到问题?【英文标题】:I have issue to remove ViewController from Navigation stack? 【发布时间】:2020-01-24 08:48:46 【问题描述】:

我有 5 个 VC,我已成功从导航堆栈中删除 ViewController。但问题是当点击导航上的后退按钮时,它正在移动到以前的 VC 并在导航栏上显示已删除的 VC。

例如:我有 5 个 VC:VC1、VC2、VC3、VC4、VC5。

现在我从 VC1 -> VC2,...... VC4 -> VC5 导航。而且我有自定义导航栏后退按钮标题。在这里,我从堆栈中删除 VC4。

当在 VC5 中单击返回按钮时,它会直接进入 VC3。但是导航栏是VC4的。现在再次单击导航栏时,它会在同一个 VC 中显示 VC3 导航栏。

如何解决此问题。我想直接点击显示VC3和vc3导航栏。

从导航堆栈中删除 VC 的代码:

guard let navigationController = self.navigationController else  return 
var navigationArray = navigationController.viewControllers // To get all UIViewController stack as Array
navigationArray.remove(at: navigationArray.count - 2) // To remove previous UIViewController
self.navigationController?.viewControllers = navigationArray

【问题讨论】:

我正在做同样的事情。请参阅this 获取您的参考资料。我没有创建自定义后退按钮。内置后退按钮有效。 【参考方案1】:

使用以下内容:

navigationController?.setViewControllers(navigationArray!, animated: true)

例如

guard let navigationController = self.navigationController else  return  
var navigationArray = navigationController.viewControllers 
navigationArray.remove(at: navigationArray.count - 2) 
navigationController.setViewControllers(navigationArray!, animated: true)

来自docs:

使用此方法更新或替换当前视图控制器堆栈 无需显式推送或弹出每个控制器。此外, 此方法允许您在不设置动画的情况下更新控制器集 更改,这可能适用于您想要的启动时间 将导航控制器返回到之前的状态。

如果启用了动画,则此方法决定哪种类型的 根据项目中的最后一项是否执行转换 数组已经在导航堆栈中。如果视图控制器是 当前在堆栈中,但不是最顶层的项目,此方法使用 流行过渡;如果它是最顶层的项目,则没有过渡 执行。如果视图控制器不在栈上,这个方法 使用推送转换。只执行一次转换,但当 该转换完成后,堆栈的全部内容是 替换为新的视图控制器。例如,如果控制器 A, B 和 C 在堆栈上,您设置控制器 D、A 和 B,这 方法使用弹出转换,结果堆栈包含 控制器 D、A 和 B。


编辑 1

在推送VC5时,使用如下代码

let vc = YourVC5()
var array = navigationController?.viewControllers
array?.removeLast()
array?.append(vc)
navigationController?.setViewControllers(array!, animated: true)

这个想法是当你将 VC5 推入堆栈时,在推入之前我们将 VC4 从列表中排除,因此默认情况下它会在 VC5 下方有 VC3,你只需要调用 navigationController?.popViewController(animated: true) 它应该直接弹出到VC3

【讨论】:

这两行的区别 ... self.navigationController?.viewControllers = navigationArray 没用..guard let navigationController = self.navigationController else return var navigationArray = navigationController.viewControllers navigationArray.remove(at: navigationArray.count - 2) self.navigationController?.viewControllers = navigationArray self.navigationController?.setViewControllers(navigationArray, animated: true) 这是我的代码,用户界面已更新但无法正常工作。得到相同的结果。 你需要删除这一行 self.navigationController?.viewControllers = navigationArray @ios 我已经用一个例子更新了我的答案,请检查【参考方案2】:

隐藏默认后退按钮并添加自定义后退按钮和操作:

override func viewDidLoad 
    super.viewDidLoad()
    self.navigationItem.hidesBackButton = true
        let customBackButton = UIBarButtonItem(title: "Back", style: UIBarButtonItem.Style.plain, target: self, action: #selector(back))
        self.navigationItem.leftBarButtonItem = customBackButton

使用 popToViewController 移回特定的视图控制器:

@objc func back(sender: UIBarButtonItem) 
    guard let navigationController = self.navigationController else  return 
var navigationArray = navigationController.viewControllers // To get all 
self.navigationController!.popToViewController(navigationArray[navigationArray.count - 2], animated: true)

【讨论】:

当你想迁移到 VC3 时在 VC5 中写入 点击导航栏后退按钮时,我想直接进入 VC3。这是默认行为。如何编写它。 将自定义后退按钮添加到导航栏并在自定义后退按钮的操作中编写此代码 @iOS 用自定义后退按钮更新了我的答案...检查 让我们continue this discussion in chat.【参考方案3】:

如果您使用自定义NavigationBar,则需要在VC5 中使用自定义后退按钮单击操作:-

@IBAction func btnBackAction(_ sender: UIButton) 
       let vc = VC3()
       self.navigationController.popToViewController(vc, animated: true)
 

如果您可以使用默认 NavigationBar 而不是需要像这样在 VC5 的导航堆栈中删除 VC4:-

guard let navigationController = self.navigationController else  return 
var navigationArray = navigationController.viewControllers // To get all UIViewController stack as Array
navigationArray.remove(at: navigationArray.count - 2) // To remove previous UIViewController
self.navigationController?.viewControllers = navigationArray

【讨论】:

【参考方案4】:

您可以使用popToViewController(_:animated:)(正如 Prakash Shaiva 上面回答的那样):

guard let navigationController = self.navigationController else  return 

var navigationArray = navigationController.viewControllers // To get all 
self.navigationController.popToViewController(navigationArray[navigationArray.count - 2], animated: true)

并尝试在 VC3 的 viewWillAppear(_:) 方法中更新您的 NavigationBar。

【讨论】:

以上是关于我在从导航堆栈中删除 ViewController 时遇到问题?的主要内容,如果未能解决你的问题,请参考以下文章

如何从导航堆栈中删除 ViewController 并且没有返回到它的选项-Swift

在导航堆栈中重新创建 viewController

有啥方法可以导航到 UInavigationcontroller 堆栈中间的 Viewcontroller

通过导航控制器推送 Viewcontroller,显示黑屏

如何清除导航堆栈以使后退按钮不出现?

将导航堆栈移动到更多选项卡