1

enter image description here斯威夫特3 iOS-编程设置,并从SplitViewController的DetailNavigationController

推新RootVC我有一个SplitViewVC具有MasterNavVC谁的根是一个TableViewVC。 SplitViewVC也有一个DetailNavVC,它有一个WhiteVC作为它的根。我有几个其他的视图控制器,我想通过我的TableViewVC:RedVC,GreenVC,BlueVC和PinkVC。我不想使用所有这些IB segue连接,所以我想以编程方式推送它们。 TableView的单元格有一个继承DetailNavVC的segue,因此所有其他的vcs都必须经过它。我正在使用iPad和iPhone的适应性。

的问题是TableView中的didSelect方法,当我尝试推到任何颜色VCS中,WhiteVC总是显示推进和弹出倒退时:

如。

即按即的TableView - > WhiteVC - > RedVC

弹出RedVC - > WhiteVC - > TableView中

我想

即按即的TableView - > RedVC

弹出RedVC - > TableView中

我试图删除WhiteVC但我一直得到了异常:

无法显示零个 viewControllers

嵌套的UINavigationController

所以我添加了WhiteVC来使这个错误无声无息,但是下面的方法都没有奏效。

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 

    switch indexPath.row{ 
     case 0: 
      //this shows the WhiteVC while pushing and popping 
      let redVC = storyboard?.instantiateViewController(withIdentifier: "RedVC") as! RedVC 
      navigationController?.pushViewController(redVC, animated: true) 
     break 
     case 1: 
      //this shows the WhiteVC while pushing but removes the backButton from the GreenVC 
      let greenVC = storyboard?.instantiateViewController(withIdentifier: GreenVC") as! GreenVC 
      navigationController?.setViewControllers([greenVC], animated: true) 
     break 
     case 2: 
      //this has the same effect as case 1 
      let blueVC = storyboard?.instantiateViewController(withIdentifier: BlueVC") as! BlueVC 
      let root = detailNavController(rootViewController: blueVC) 
      navigationController?.pushViewController(root, animated: true) 
     break 
     case 3: 
      //this shows the WhiteVC pushing but doesn't show it popping 
      let masterNav = splitViewController?.viewControllers.last as! MasterNavVC 
      let detailNav = masterNav.viewControllers.last as! DetailNavVC 
      let pinkVC = storyboard?.instantiateViewController(withIdentifier: "PinkVC") as! PinkVC 
      detailNav.setViewControllers([pinkVC], animated: true) 
     break 

情况下3来到衣柜作为WhiteVC显示,同时推动,但它并没有显示弹出(它正确地弹出来根):

即按即的TableView - > WhiteVC - > PinkVC

弹出PinkVC - > TableView中

我想要以编程方式推送到其他颜色的vcs(当然在点击他们选中的单元格后)而不显示WhiteVC。我怎么做?

+0

虽然我寻求类似的解决方案,并具有目前没有答案,我想承认最优秀的问题提法。 –

+0

@drew谢谢你的赞美!我在这个月前得到了一些帮助。如果您需要,我今天晚些时候可以发布答案。其实很简单。 –

+0

兰斯,请做。我的情况正在令我慌乱。我面临使用SlideMenu回购的挑战,该回购转换为SplitView范例,必须将其主页左侧按钮转换回SlideMenu范例,然而当打开时,必须显示Apple的SplitView范例的根视图>>驾驶我的巴蒂;)我我正在考虑一个类似于你的帖子来布置它。 –

回答

0

首先让我说苹果建议SpiltVC以root身份开始。我遇到的问题是,如果使用TabBarVC作为根目录,则必须将其放在containerView中,然后将containerView作为root用户创建一个NavVC,并将其作为SplitVC的根目录。

SplitVC > NavVC > ContainerVC > TabBarVC //this wasn't working out 

我决定使用TabBarVC作为根目录并为每个选项卡添加一个单独的SplitVC。如果你看下面图片的左边,这是苹果的MasterDetailApp在启动时的样子。场景的右侧是我使用的布局。

enter image description here

在图像的右侧,我有一个的TabBar为根,每个标签都有一个SplitVC每个SplitVc都有它自己的NavVC它本身有它自己的TableVC,因为它的根:

  ____SplitVC -- NavVC -- TableVC //this would be tab 0 and where we will focus 
     /
     /
TabBarVC         //all the other color vcs I want to get to from the TableVC in tab 0 
     \ 
      \____SplitVC -- NavVC -- TableVC 

有关未使用的图像右侧的注意事项包括DetailNavigationController,如MasterDetailApp中包含的内容。

我只会专注于从TabBar的第一个选项卡推送vcs,因为您会为TabBar的第二个选项卡使用相同的方法。

要的appDelegate的didFinishLaunching开始,你会简单地添加你想要的土地上首先作为selectedIndex处的标签:

AppDelegate: 

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 

     //I subclassed the TabBarVC with the name TabBarController 

     let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil) 
     let tabBarVC: TabBarController = mainStoryboard.instantiateViewController(withIdentifier: "TabBarController") as! TabBarController 
     tabBarController.selectedIndex = 0 
     window?.rootViewController = tabBarController 

     window?.makeKeyAndVisible() 
     return true 
} 

仅供参考这里是VC的对标签0的流量和名称:

TabBarContoller > TabZeroSplitVC > TabZeroNavVC > SettingsVC 

启动这种方式会给我SettingsVC,它在iPad上将在左侧(主侧)在分屏模式下。您还必须遵守UISplitViewControllerDelegate,并在viewDidLoad中进行设置,使其显示分割屏幕,并在左侧显示主屏幕,并在右侧显示详细信息。

SettingsVC: UIViewController, UISplitViewControllerDelegate{ 

@IBOutlet weak fileprivate var tableView: UITableView! 

var colors = ["RedVC", "GreenVC", "BlueVC", "PinkVC"] 

override func viewDidLoad() { 
    super.viewDidLoad() 

    splitViewController?.delegate = self 

    //this keeps it in splitScreen mode 
    splitViewController?.preferredDisplayMode = UISplitViewControllerDisplayMode.allVisible 
} 

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return self.colors.count 
} 

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCell(withIdentifier: "ColorsCell", for: indexPath) as! ColorsCell 

     cell.titleLabel?.text = self.colors[indexPath.row] 
     return cell 
} 

由于我没有包括故事板一DetailNavigationController然后屏幕(详细侧)的右侧是一片空白。因此,在启动,你会看到一个屏幕,看起来像这样:

enter image description here

我们的想法是第一编程方式添加一个NavVC,然后以编程添加WhiteVC,因为它的根。这样,WhiteVC将最初显示在屏幕的右侧。关键是使用splitVC的showDetailViewController(vc: UIViewController, sender: Any?)以编程方式显示它。顺便说一句,将nav添加为类变量很重要,因为这是我们将用来显示其他颜色的vcs。

SettingsVC: UIViewController, UISplitViewControllerDelegate{ 

@IBOutlet weak fileprivate var tableView: UITableView! 

var colors = ["RedVC", "GreenVC", "BlueVC", "PinkVC"] 

var whiteVC: WhiteController? //the one from the storyboard 

var nav: UINavigationController? //this will represent the DetailNavigationController from Apple's MasterDetailApp 

override func viewDidLoad() { 
    super.viewDidLoad() 

    splitViewController?.delegate = self 
    splitViewController?.preferredDisplayMode = UISplitViewControllerDisplayMode.allVisible 

    //1st instantiate the WhiteVC that was created in storyboard 
    self.whiteVC = storyboard?.instantiateViewController(withIdentifier: "WhiteController") as? WhiteController 

    //2nd add it to the programmatic navigationController as it's root 
    self.nav = UINavigationController(rootViewController: whiteVC!) 

    //3rd use the splitVC method to show the nav on the right side of scene 
    splitViewController?.showDetailViewController(self.nav!, sender: self 
} 

现在推出时的情景将是这样的:

enter image description here

我们的答案如何在任何颜色VCS的推动,而不包括WhiteVC的问题。你所要做的就是将任何颜色的vc作为根添加到作为类变量创建的编程导航中。而且里面的tableView的didSelectRow是您添加它,并从

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 

switch indexPath.row{ 

     case 0: 
      let redVC = storyboard?.instantiateViewController(withIdentifier: "RedController") as! RedController 
      self.nav = UINavigationController(rootViewController: redVC) 
      splitViewController?.showDetailViewController(self.nav! , sender: self) 
      break 

     case 1: 
      let greenVC = storyboard?.instantiateViewController(withIdentifier: "GreenController") as! GreenController 
      self.nav = UINavigationController(rootViewController: greenVC) 
      splitViewController?.showDetailViewController(self.nav! , sender: self) 
      break 

     case 2: 
      let blueVC = storyboard?.instantiateViewController(withIdentifier: "BlueController") as! BlueController 
      self.nav = UINavigationController(rootViewController: blueVC) 
      splitViewController?.showDetailViewController(self.nav! , sender: self) 
      break 

     case 3: 
      let pinkVC = storyboard?.instantiateViewController(withIdentifier: "PinkController") as! PinkController 
      self.nav = UINavigationController(rootViewController: PinkVC) 
      splitViewController?.showDetailViewController(self.nav! , sender: self) 
      break 

} 

显示现在,如果你选择了一个标RedVC你会得到这个(应该在RedVC的顶部的导航栏的电池,但我忘了补充它在Photoshop):

enter image description here

如果你看一下里面didSelectRow你会看到导航现在有一个新的根这是redVC(它最初使用WhiteVC在viewDidLoad中)。由于您更改了根目录,因此WhiteVC不再处于层次结构中。对于其他任何颜色都会遵循同样的事情。如果你选择了PinkVC你会得到(应该在PinkVC的顶部的导航栏,但我忘了将它添加在Photoshop):

enter image description here

在任何情况下,所有你需要做的就是设置一个新的根的导航。如果你想补充一点,延长认为,双展开箭头的东西向外

enter image description here

你还能在didSelectRow

 case 0: 
      let redVC = storyboard?.instantiateViewController(withIdentifier: "RedController") as! RedController 
      self.nav = UINavigationController(rootViewController: redVC) 

      //these 2 lines of code are what adds the double expand arrow 
      self.nav?.topViewController?.navigationItem.leftBarButtonItem = splitViewController?.displayModeButtonItem 
      self.nav?.topViewController?.navigationItem.leftItemsSupplementBackButton = true 

      splitViewController?.showDetailViewController(self.nav! , sender: self) 
      break 

      //add the same exact 2 lines for every other case 

最后一件事添加。这是我碰到的一个大问题,我相信其他人可能会遇到这个问题,因为这个SplitVC不是root。我们假设在启动时在选项卡零上显示另一个vc(即OrangeVC)而不是SettingsVC。问题是设置为:

TabBarContoller > TabZeroSplitVC > TabZeroNavVC > SettingsVC 

由于故事板具有SettingsVC作为TabZeroNavVC的根,你将不得不改变它在的appDelegate的didFinishLaunching(或您的登录屏幕等)。

的代码使用它会是:

AppDelegate: 

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 

     //I subclassed the TabBarVC with the name TabBarController 

     let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil) 
     let tabBarVC: TabBarController = mainStoryboard.instantiateViewController(withIdentifier: "TabBarController") as! TabBarController 
     tabBarController.selectedIndex = 0 

     //first you have to get to the splitVC on the first tab 
     let tabZeroSplitVC = tabBarController.viewControllers![0] as! TabZeroSplitController 

     //second you have to get to the navVC that's connected to the splitVC 
     let tabZeroNavVC = tabZeroSplitVC.childViewControllers[0] as! TabZeroNavController 

     //third instantiate the vc that you want to appear upon launch 
     let orangeVC = mainStoryboard.instantiateViewController(withIdentifier: "OrangeController") as! OrangeController 

     //the navVC has a method to set a new array of vcs. Just add the orangeVC in here (make sure to put it in array brackets) 
     tabZeroNavVC.setViewControllers([orangeVC], animated: true) 

     window?.rootViewController = tabBarController 

     window?.makeKeyAndVisible() 
     return true 
} 

当您启动OrangeVC会显示。由于OrangeVC不是tableView,你可能想要显示全屏。一定要添加UISplitViewControllerDelegate和viewDidLoad中添加:

OrangeVC: UIViewController, UISplitViewControllerDelegate{ 

override func viewDidLoad() { 
     super.viewDidLoad() 

     splitViewController?.delegate = self 

     //this will hide splitScreen and will only show fullScreen 
     splitViewController?.preferredDisplayMode = UISplitViewControllerDisplayMode.primaryHidden 
} 

你必须的,而不是有一个分隔的橙色经推出全屏。

即使这些链接使用SplitVC为根,这些都是有关配置SplitVC一些非常优秀的博客文章:

SplitVC-1

SplitVC-2

SplitVC-3

SplitVC-4

SplitVC-5

SplitVC-7

+0

嘿兰斯,感谢您对我删除错误发布的评论的评论。当然,我理解你的想法,抓住有问题的导航员等推进/呈现是第二天性的。我经常这样做,并为iPhone使用案例做了这样的工作(我将每个didSelect单元格func分解成分支来管理不同的布局要求,我的iPhone分支在30秒内编码,如前所述工作正常。 UISplitViewController管理所有的东西,详细视图中的导航控制器是零,我测试了很多不同的方式,它是零,因此我的困境 –

+0

@drew我不知道如果你使用一个新创建的导航。如果以编程方式在prepare或didSelect中创建一个nav,它将如何变为零?您是否尝试过我所建议的?这是我在4个不同的SplitVCs上使用的4种不同的选项卡的方法,我也在整个应用程序中使用它我在那里创建一个导航,以呈现或推送一个vc。你所使用的vcs的故事板布局是什么? –

+0

如上所述,我还没有时间回顾你的神话般的努力,在那里,我是确定存在解决方案。我将更新我的sep稍后讨论这个问题。谢谢*你* –