在显示之前将 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 [关闭]
在 iOS 7 上使用 Person ViewController 重新加载/更改显示的人
在加载 ViewController 之前加载 MapView