0

So I am using some Storyboard References to bring in some structure. Now I am trying to change the ViewController from code, but I am not able to use a ViewController from a different Storyboard. My Code is currently looking like that:

func showCommunityDetail(){
    let storyBoard : UIStoryboard = UIStoryboard(name: "community", bundle:nil)
    let nextViewController = storyBoard.instantiateViewController(withIdentifier: "communityDetail") as! CommunityViewController
    self.present(nextViewController, animated:true, completion:nil)
}

The community Storyboard contains the communityDetail controller, but the view which is shown at the moment this code is executed, is in a different storyboard.

How can I present between different Storyboards?

Update

I updated my code to the following line:

  let detailViewController = UIStoryboard(name: "community", bundle: nil).instantiateViewController(withIdentifier: "communityDetail");

However, now i get a new error: whose view is not in the window hierarchy!

Fabio ha
  • 553
  • 1
  • 8
  • 29
  • are u using more than one storyboard? if Yes then why? – Maddy May 15 '17 at 08:13
  • I have about 20 different ViewControllers and I think it's easier for a team to work in different files. – Fabio ha May 15 '17 at 08:17
  • It is, i also prefer having a view controller per storyboard (unless its directly connected to that view controller) – Pochi May 15 '17 at 08:18
  • @Fabioha if different developers are working on the project, don't you think that xib way would be better to avoid merge conflicts etc instead of using different storyboard. – Maddy May 15 '17 at 08:45
  • @Maddy I don't have a lot of experience in ios development so I don't really see the advantages or disadvantages. – Fabio ha May 15 '17 at 08:50
  • Yes, there is one navigation Controller. – Fabio ha May 15 '17 at 09:13
  • move your code to viewdidappear method – Maddy May 15 '17 at 09:14
  • The thing is, the View should change on a Click in the collectionView so I can't execute it in the viewWillAppear. – Fabio ha May 15 '17 at 09:18
  • Then you have to provide some more info because i have created the sample and used your code and i was able to navigate to other controller – Maddy May 15 '17 at 09:23
  • try this: `let newViewController = UIStoryboard(name: "community", bundle: nil).instantiateViewController(withIdentifier: "communityDetail") UIApplication.topViewController()?.present(newViewController, animated: true, completion: nil)` – Maddy May 15 '17 at 09:26
  • So I you pointed me in the right direction @Maddy. However for your code to work, you need to write an extension for the UIApplication. – Fabio ha May 15 '17 at 09:34
  • Issue resolved? – Maddy May 15 '17 at 09:35
  • Yeah u r rite.. – Maddy May 15 '17 at 09:36

2 Answers2

1

To present a view controller in a different storyboard.

1) Make sure the "Initial View Controller" property is set for the entry ViewController in each of the storyboards.

Present it:

let vcToPresent = UIStoryboard(name: "StoryboardName", bundle: nil).instantiateInitialViewController();

// Ensure its of the type that you want, so that you can pass info to it
guard let specialVC = vcToPresent as? SpecialViewController else {
        return
    }

specialVC.someProperty = somePropertyToPass

self.present(specialVC, animated: true, completion: nil)

Edit:

To instantiate a different viewcontroller (other than the one who is marked as initial) the following method can be used:

func instantiateViewController(withIdentifier identifier: String) -> UIViewController

Link to the documentation: https://developer.apple.com/reference/uikit/uistoryboard/1616214-instantiateviewcontroller

Note that you MUST set an identifier on the interface builder for the viewcontroller you want to use this method with.

Pochi
  • 13,391
  • 3
  • 64
  • 104
  • So If I have more than one ViewController in the Storyboard it doesn't work right? Is there a way or should I create a new Storyboard? – Fabio ha May 15 '17 at 08:27
  • Yes it does. Just set an identifier in the interface builder and use this method instead: instantiateViewController(withIdentifier:) https://developer.apple.com/reference/uikit/uistoryboard/1616214-instantiateviewcontroller – Pochi May 15 '17 at 08:31
  • So I tried it with instantiateViewController but got a new error. I updated the post with the new error. I also set the Storyboard Id to communityDetail. – Fabio ha May 15 '17 at 08:44
  • sorry, didn't see your response until now. The error you are getting is the following: http://stackoverflow.com/questions/11862883/whose-view-is-not-in-the-window-hierarchy by the way, i think you already solved your issue by finding out the current top vc as you described in your comments. But you should know that this is NOT a very safe approach. You might experience issues if it happens to run while an UIAlertView is on display for example. – Pochi May 16 '17 at 00:54
0

Just worked on the requirement you asked for and it is in swift 2.2. Try it out it works this way.

var nextViewController : CommunityViewController!
func showCommunityDetail() {
    let mainStoryboard = UIStoryboard(name: "community", bundle: nil)
    nextViewController = mainStoryboard.instantiateViewControllerWithIdentifier("communityDetail") as! CommunityViewController
    addChildViewController(nextViewController)
// Optionally you can change the frame of the view controller to be added
    nextViewController.view.frame = CGRect(x: 0, y: 0 , width: view.frame.width, height: view.frame.height)
    view.addSubview(nextViewController.view)
    nextViewController.didMoveToParentViewController(self)
}
Praveen Kumar
  • 298
  • 2
  • 15
  • No, he want to navigate to other controller that is in separate storyboard, but in your solution you are adding it as child controller i.e. completely different thing – Maddy May 15 '17 at 09:34
  • Oh okay, it can be done via segue and an easy one to implement. – Praveen Kumar May 15 '17 at 09:39