在显示之前将 ViewController 加载到 ContainerView 中,因此没有可见的过渡

Posted

技术标签:

【中文标题】在显示之前将 ViewController 加载到 ContainerView 中,因此没有可见的过渡【英文标题】:Load ViewController into ContainerView prior to showing so no transition is visible 【发布时间】:2019-05-28 03:44:46 【问题描述】:

使用 Swift 4+、ios 11.4+、Xcode 10+

我正在使用带有导航控制器的 ContainerView 来加载多个 ViewController。

此外,持有 ContainerView 的 ViewController 也被推送到不同的 NavigationController 堆栈中。

看这张图:

“菜单”是堆栈中的根控制器。 我正在将另一个 ViewController (TopViewController) 推送到同一个堆栈上 - 到目前为止一切顺利。

我的问题是我想用不同的 ViewController (Item1) “预加载” TopViewController > ContainerView TopViewController 变得可见之前。

除了 Item1 之外,我还需要以这种方式“预加载”其他 ViewController。

我曾尝试在 TopViewController 中使用“viewDidLoad”来推送 Item1,

toVC = storyboard?.instantiateViewController(withIdentifier: "Item1") as! Item1
TopNav.pushViewController(toVC, animated: true)

它可以工作 - 但只有在 TopViewController 变得可见之后。 这意味着您可以看到 Item1 “弹出”到视图中,而不是已经可见。

我也在 Menu VC 中尝试过此代码,但它不会将任何内容推送到 ContainerView。

let toVC = self.storyboard?.instantiateViewController(withIdentifier: "TopViewController") as! TopViewController
        
// Tried this to 'pre-load' the next VC - shows no VC, and disables 'back' navigation
let toNav = toVC.navigationController
let nextVC = storyboard?.instantiateViewController(withIdentifier: "Item1") as! Item1
// Neither of the lines below loads the Item1 VC....
//toNav?.viewControllers = [nextVC]
toNav.pushViewController(toVC, animated: true)

如何在带有 ContainerView 的 VC 变得可见之前将 Item1 推送到 ContainerView 的导航堆栈上?

仅供参考:您可以在此处下载我的示例项目:https://gitlab.com/whoit/newviews

【问题讨论】:

我正在使用 Storyboard“ContainerView”对象。 【参考方案1】:
   TopNav.pushViewController(toVC, animated: true)

它可以工作 - 但只有在 TopViewController 变得可见之后。

因为您要求动画。将 animated: true 更改为 animated: false 如果这是你想要的。


前面说的没错,但是你的项目还有很多其他的问题。

最重要的是,您的容器视图没有约束。这会导致它以错误的大小结束。在情节提要中给它约束。

其次,按我上面说的做:用false 动画推送toVC

第三,你需要预加载你的顶视图控制器的视图,像这样:

@IBAction func Item1_Tap(_ sender: UIButton) 
    let toVC = self.storyboard?.instantiateViewController(
        withIdentifier: "TopViewController") as! TopViewController
    toVC.loadViewIfNeeded() // add this line
    // then delete all the other useless stuff

结果:

【讨论】:

更改值不会产生影响。使用“.viewControllers = [nextVC]”与使用“false”基本相同。无论哪种方式,新的 VC 首先变得可见,然后 Item1 会弹出。 好吧,也许你需要让顶视图控制器提前加载它的视图? 如果您有兴趣,我刚刚在 OP 中添加了指向我的示例项目的链接... 是的 - 这是解决它的“loadViewIfNeeded”方法 - 谢谢! 是的,当我说“让顶视图控制器更早加载其视图”时,这就是我在评论中的意思。【参考方案2】:

我认为您想要的是一种管理子视图控制器的方法,对吗? (childVC1 = item1,childVC2 = item2,等等)

如果是这样,this may help。

另一种方法是将您的TopViewController 嵌入TabBarController,并隐藏标签栏。然后,当一个项目被选中时,您加载 TopViewController 以及与该项目关联的选项卡索引。

编辑:

您可以做的是使用导航控制器代替您的TopViewContorller,它根据所选项目设置rootViewController。就您的代码而言,需要进行一些维护工作才能顺利完成:

    摆脱您的基本UINavigationController,并将您的MenuViewController 作为您的初始ViewController。 在每个与同一个UINavigationController 转接的项目上添加转接。

    MenuViewController 中覆盖prepare(for:, sender:) 并初始化与所选项目关联的UIViewController。您可以通过命名 segue 并打开名称,或将发件人与按钮匹配来做到这一点。

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
        switch segue.identifier 
    
        case "item1Segue":
            guard let item1VC = storyboard?.instantiateViewController(withIdentifier: "Item1") else  return assertionFailure() 
            item1VC.title = "Item1"
            (segue.destination as UINavigationController)?.setViewControllers([item1VC], animated: false)
    
        case "item2Segue":
            guard let item2VC = storyboard?.instantiateViewController(withIdentifier: "Item2") else  return assertionFailure() 
            item2VC.title = "Item2" UINavigationController)?.setViewControllers([item2VC], animated: false)
            // And so on
        
    
    

    要获得与 TopViewController 相同的 UI,请在 Item viewControllers 中添加一个后退按钮和条形按钮,在代码中设置标题后跟标题。

【讨论】:

如果您有兴趣,我刚刚在 OP 中添加了指向我的示例项目的链接... 立即查看 我很确定它可以在不添加更多控件的情况下完成 - 我更喜欢这样...... 根据您的代码库更新答案,请稍等 我更新了我的答案,如果您有兴趣,我很乐意帮助您查看您的代码的其他内容。我的 twitter 和 git 链接在我的个人资料中

以上是关于在显示之前将 ViewController 加载到 ContainerView 中,因此没有可见的过渡的主要内容,如果未能解决你的问题,请参考以下文章

如何从本地 JSON 文件将数据加载到 ViewController [关闭]

将另一个 nib 加载到 viewController

在 iOS 7 上使用 Person ViewController 重新加载/更改显示的人

在加载 ViewController 之前加载 MapView

为啥显示不正确的 ViewController?以及如何显示正确的?

试图从 didSelectCellAtIndex 将图片加载到新的 ViewController