【问题标题】:performSegue pushes next view controller into unwanted view hierarchyperformSegue 将下一个视图控制器推送到不需要的视图层次结构中
【发布时间】:2018-06-07 04:50:01
【问题描述】:

我正在构建一个基于导航的应用程序,您可以在其中使用底部选项卡进行导航,并且每个选项卡都有自己的导航堆栈。 大部分部分按预期工作,但一个特定选项卡的行为异常。

发生了什么:

在浏览了几个视图控制器之后,比如说 [A] [B] [C] 和 [D],下一个控制器 [E] 突然离开了导航堆栈。 当它发生时,视图看起来像模态呈现,导航堆栈看起来像这样。

(lldb) po [[[UIWindow keyWindow] rootViewController] _printHierarchy]

<MyApp.CRTabBarController 0x112026800>, state: disappeared, view: <UILayoutContainerView 0x111e1fa00> not in the window
   | <UINavigationController 0x112027a00>, state: disappeared, view: <UILayoutContainerView 0x111e23f50> not in the window
   |    | <MyApp.X1_ViewController 0x111d12490>, state: disappeared, view: <UIView 0x111e32d70> not in the window
   |    |    | <MyApp.InsideX1_ViewController 0x112096200>, state: disappeared, view: <UIView 0x111e35d90> not in the window
   | <UINavigationController 0x11200aa00>, state: disappeared, view: (view not loaded)
   |    | <MyApp.X2_ViewController 0x111d22360>, state: disappeared, view: (view not loaded)
   | <UINavigationController 0x11205a200>, state: disappeared, view: (view not loaded)
   |    | <MyApp.X3_Controller 0x11205a800>, state: disappeared, view: (view not loaded)
   | <UINavigationController 0x112059600>, state: disappeared, view: (view not loaded)
   |    | <MyApp.X4_ViewController 0x111e0cea0>, state: disappeared, view: (view not loaded)
   | <UINavigationController 0x112058e00>, state: disappeared, view: <UILayoutContainerView 0x111d50370> not in the window
   |    | <MyApp.A_ViewController 0x111d25f70>, state: disappeared, view: <UIView 0x116e0ad90> not in the window
   |    |    | <MyApp.PageViewController 0x112891400>, state: disappeared, view: <_UIPageViewControllerContentView 0x113feb0a0> not in the window
   |    |    |    | <MyApp.InnerPageViewController 0x111ee3bf0>, state: disappeared, view: <UIView 0x111e6e000> not in the window
   |    | <MyApp.B_ViewController 0x113ee8280>, state: disappeared, view: <UIView 0x116e37cf0> not in the window
   |    | <MyApp.C_Controller 0x118f06f10>, state: disappeared, view: <UIView 0x113ee46f0> not in the window
   |    | <MyApp.D_ViewController 0x116e5f580>, state: disappeared, view: <UIView 0x118f2fe70> not in the window
   + <E_ViewController 0x116ecff30>, state: appeared, view: <UIView 0x111ee43f0>, presented with: <_UIFullscreenPresentationController 0x116e13420>

从顶部开始的四个导航控制器是不活动的选项卡,这里不感兴趣。在最后一个选项卡的导航中,您可以看到A_ to D_ - ViewController's。那么E_ViewController在不同的导航层次中,这就是这里的问题。

代码很简单,D_ViewController 只是像这样调用performSegue

self.performSegue(withIdentifier: "goto_E", sender: self)

Segue 设置也很正常,我认为。它只是指定 id 和“显示”作为样式。 SegueD_ViewController 连接到E_ViewController,因此它可以被称为performSegue's 标识符arg。

有人有过这样的经历吗?猜猜可能的原因?

【问题讨论】:

  • 从 D 到 E 的转场是否与链中的其他转场相同,例如 B 到 C 或 C 到 D?
  • 是的,它们都是一样的。我通过单击 segues 进行了视觉比较,除了标识符之外没有任何变化。
  • 他们以同样的方式去 B_ViewController 到 C_ViewController,C_ViewController 到 D_ViewController?
  • 我对所有这些转换都使用 performSegue,并且转换 A 到 B、B 到 C 和 C 到 D 都执行相同的滑动效果。正如我在原始帖子中所写,控制器(A~D)被卡在正确的导航堆栈中。

标签: ios swift uiviewcontroller uinavigationcontroller uistoryboard


【解决方案1】:

//移除segue并实例化

extension UIViewController {

     class func instantiate(fromStoryboard name: String, id: String) -> Self? {
         return instantiateHelper(fromStoryboard: name, id: id)
     }

     private class func instantiateHelper<T>(fromStoryboard name: String, id: String) -> T? {
         let storyboard = UIStoryboard(name: name, bundle: nil)
         let controller = storyboard.instantiateViewController(withIdentifier: id) as? T
         return controller
     }
}

用途:-

 guard let vc = ViewController.instantiate(fromStoryboard: "Main", id: "ViewController") else { return }
 self.navigationController?.pushViewController(vc, animated: true)

【讨论】:

  • 为什么?删除segue并改用实例化的原因是什么?是否应该对所有内容都这样做,然后从未使用过 segues?
  • 看起来是一个很好的解决方法。重点是从Storyboard中抓取VC,直接推送到导航控制器,对吧?让我试一试。
  • @UpholderOfTruth 很多时候 segue 不能正常工作。所以,最好实例化。
  • 只有在设置不正确的情况下,segue 才能正常工作。只要一切编码正确,就不会有问题。实例化肯定不是更好,因为这会否定情节提要的许多功能(以及 WWDC 讨论的大部分内容)。
【解决方案2】:

感谢cmets,但我已经自己解决了。 说起来很尴尬,但原因很愚蠢,它在调用performSegue 之前就调用了popViewController

这个pop call是因为我的视图结构变化的遗产,而且因为写在分开的地方所以很难注意到。

虽然这不是一个直接的答案,但直接从 Storyboard 实例化的方法有助于澄清问题。谢谢,Pratyush。

但完全出乎意料的是,在拉取 segue 之前弹出视图控制器会导致这种行为。 希望这可以暗示其他人的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-16
    • 2020-01-14
    • 2018-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-30
    • 1970-01-01
    相关资源
    最近更新 更多