如何从主视图控制器在详细视图控制器中推送新视图?

Posted

技术标签:

【中文标题】如何从主视图控制器在详细视图控制器中推送新视图?【英文标题】:How to push new view in detail view controller from master view controller? 【发布时间】:2016-06-04 22:42:48 【问题描述】:

我一直在摸索,试图弄清楚如何做到这一点。如果有人有一些见解,将不胜感激。我尝试使用 segues 和 push/presentViewController 方法来做到这一点。使用 pushViewController 没有任何反应。

场景: 拆分视图控制器连接了两个导航控制器(一个作为主控,一个作为细节)。主导航控制器有一个包含各种单元格的表单,这些单元格应该控制在 iPad 上处于横向模式时右侧详细视图中显示的内容。连接到详细视图的导航控制器具有连接到它的故事板引用(其中 3 个)。

我想做的事:从主视图控制器(即应用程序菜单),我想在保持导航栏的同时控制详细视图中显示的内容。

尝试 1:

let detailVC = self.splitViewController!.viewControllers[1]
let newVC = UIStoryboard(name: "D", bundle: nil).instantiateViewControllerWithIdentifier("P")
detailVC.self.navigationController?.pushViewController(newVC, animated: true)

尝试 2:

let detailVC = self.splitViewController!.viewControllers[1]
let newVC = UIStoryboard(name: "D", bundle: nil).instantiateViewControllerWithIdentifier("P")
detailVC.performSegueWithIdentifier("navP", sender: self)

我遇到的另一个相关问题...如果用户在几个菜单选项之间跳了很多次,如何“重置”导航栏中的后退按钮的历史记录,以防止单击后退会循环您相同的几个视图?

【问题讨论】:

【参考方案1】:

您不应该推送视图控制器或执行 segue,而是调用 showViewController。

您肯定需要维护导航栏还是可以显示不同的 UINavigationBars(通过显示嵌入在 UINavigationViewController 中的视图控制器)?

或者只显示一个视图控制器并使用您在视图控制器中添加的逻辑来更改主视图控制器控制下的内容。

【讨论】:

“尝试 1”中的 pushViewController 和 showViewController 什么都不做。单元格突出显示,然后屏幕上没有任何变化。我需要保留导航栏,因为我希望用户能够在需要时快速返回,还因为我使用的表单框架(Eureka)在新视图中显示大列表时需要导航栏.【参考方案2】:

在尝试了一些最佳方法后,我解决了这个问题。 :) 以下解决方案适用于所有设备(iPhone/iPad)。

为 UISplitViewController 定义扩展:

基于https://***.com/users/4418308/santiago-bendavid的修改版

extension UISplitViewController 
    func toggleMasterView() 
        if UIScreen.mainScreen().bounds.height > UIScreen.mainScreen().bounds.width 
            var nextDisplayMode: UISplitViewControllerDisplayMode
            switch(self.preferredDisplayMode)
            case .PrimaryHidden:
                nextDisplayMode = .AllVisible
            default:
                nextDisplayMode = .PrimaryHidden
            
            UIView.animateWithDuration(0.2)  () -> Void in
                self.preferredDisplayMode = nextDisplayMode
            
         else 
            // do nothing
        
    

主导航控制器的根视图控制器中的代码:

let newVC = UIStoryboard(name: "some_storyboard_id", bundle: nil).instantiateInitialViewController()
if self.splitViewController!.viewControllers.count == 2 
    let detailVC = self.splitViewController!.viewControllers[self.splitViewController!.viewControllers.endIndex - 1]
    if detailVC.childViewControllers[detailVC.childViewControllers.count - 1].restorationIdentifier! != "some_id_here"  
        detailVC.childViewControllers[0].navigationController?.pushViewController(newVC!, animated: true)
    
    self.splitViewController!.toggleMasterView()                
    self.navigationController?.splitViewController!.preferredDisplayMode = .Automatic
 else 
    self.navigationController?.pushViewController(newVC!, animated: true)

此代码适用于常规 iPhone(非 Plus),其中主视图控制器是用于导航的唯一控制器。在 iPad 和 iPhone 6/6s+ 型号(与 iPad 相同)上,我使用恢复 ID 属性检查当前视图是否已经存在,如果新视图与屏幕上已经呈现的视图不同,则显示新视图,并且如果我们处于纵向模式,则关闭主视图控制器。如果在横向,我们将其保留在屏幕上(默认行为)。

【讨论】:

以上是关于如何从主视图控制器在详细视图控制器中推送新视图?的主要内容,如果未能解决你的问题,请参考以下文章

通过 UIScrollView 推送 ViewController

如何从嵌入在视图控制器中的表视图中的集合视图中传递数据并推送新的视图控制器?

模态下的弹出/推送视图

从标签栏应用程序中的表格视图推送新的视图控制器

从主视图控制器推送详细视图控制器

使用导航控制器从 mapView 推送详细视图