Display multiple UIViewControllers in Storyboard by implementing codes - ios

More specific,
Let's say I have a UIViewController A, when I press a button in A that is created by code, I would like to display another UIViewController B, where B is designed in the storyboard. Can it be done by coding, but not using the connections between view controllers in the storyboard. Thanks.

Absolutely,
Make sure you have added the storyBoardIdentifier to ViewController B.
Finally, In your ViewController A :
let YourStoryBoard = UIStoryboard(name: "YourStoryBoard", bundle: nil)
let vc = YourStoryBoard.instantiateViewController(withIdentifier: "VCB_StoryBoard_Identifier") as! ViewControllerB
If your ViewController has a UINavigationController embedded to it then,
self.navigationController?.pushViewController(vc, animated: true)
Else present ViewController B from ViewController A
self.present(vc, animated: true, completion: nil)
EDIT:
Set your storyboard identifier as shown in image below
Associate your ViewControllerB class with storyboard VC by setting the ViewController's class. As shown below.

You have to make a new cocoa touch class -> UIViewController -> "ViewContollerB"
Add the name in the storyboard to the view and than you can do:
let storyboard = UIStoryboard(name: "YourStoryBoard", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "VCB_StoryBoard_Identifier") as! ViewContollerB

Try this:
On button tap in UIViewController A,
func onTapButton()
{
let controller = UIStoryboard.init(name: "YOUR_STORYBOARD_NAME", bundle: nil).instantiateViewController(withIdentifier: "ViewControllerBIdentifier") as! ViewControllerB
self.present(controller, animated: true, completion: nil)
}
Here,
ViewControllerBIdentifier : StoryboardID corresponding to UIViewController B
ViewControllerB : class corresponding to UIViewController B

Related

How to push a new view controller from a view

I created a view in .xib. On it, I placed a button on which I want to open another ViewController. I assigned a storyboardID to this ViewController. But I can't push the new controller, how can this problem be solved?
My code:
class MyView: UIView {
...
#IBAction func buttonPressed(_ sender: Any) {
let storyboard = UIStoryboard.init(name: "ViewController", bundle: Bundle.init())
let vc = storyboard.instantiateViewController(withIdentifier: "VC") as! ViewController
let navigationController = UINavigationController.init()
navigationController.pushViewController(vc, animated: true)
}
...
}
class ViewController: UIViewController {
...
}
Xcode gives this error:
'Could not find a storyboard named' ViewController'
but I checked there are no errors. I reloaded Xcode - no result.
Seems you have more than one issue.
You are trying to push a UIViewController into a non presented UINavigationController
You are creating an instance from a UIStoryboard with wrong identifier
First you need to choose the correct UIStoryboard which I am assuming it's main, then you have to present the UINavigationController from the holder UIViewController or trying to push from that UIViewController if it's has a UINavigationController,
Part 1: Fixing the instances,
let storyboard = UIStoryboard.init(name: "main", bundle: Bundle())
let vc = storyboard.instantiateViewController(withIdentifier: "VC") as! ViewController
let navigationController = UINavigationController(rootViewController: vc)
Now you have a navigationController that holds a your VC
Part 2: You want to present this navigation from your holding VC you can either add a listener to the UIButton from that VC and present/push from there
so lets wrap this up create a function in your VC that holds the UIView
#objc func pushToMyVc() {
let storyboard = UIStoryboard.init(name: "main", bundle: Bundle())
let vc = storyboard.instantiateViewController(withIdentifier: "VC") as! ViewController
let navigationController = UINavigationController(rootViewController: vc)
}
And in your UIView add this variable var selector: (() -> Void)?
Now in #IBAction func buttonPressed call this function selector?()
Now all we need is to pass what function I want to use when this button gets clicked in our case the function pushToMyVC that we put in our main UIViewController so in our didLoad or wherever you're calling this custom view
set the selector like this
myView.selector = pushtoMyVC
Side Note: you can't present/push UIViewController from non
UIViewController classes
Try changing how you fetch the storyboard from
let storyboard = UIStoryboard.init(name: "ViewController", bundle: Bundle.init())
to
let storyboard = UIStoryboard(name: "ViewController", bundle: nil)
note that the storyboard ID needs to be exactly ViewController.
If this still shows the same error, I'd say you have an issue with the storyboard target membership, so check that in the file inspector on the right side of the Xcode editor.
You should check your Storyboard file name again, because when you want to initiate a UIViewController from a Storyboard file, the name parameter in UIStoryboard initiation has to be exactly the same as the Storyboard file name.
#IBAction func buttonPressed(_ sender: Any) {
// Let's say that you have a Storyboard file named ViewController.storyboard and a UIViewController class named ViewController.swift
let destinationVC = UIStoryboard(name: "ViewController", bundle: nil).instantiateViewController(withIdentifier: "VC") as! ViewController
self.navigationController?.pushViewController(destinationVC, animated: true)
}
Hope this helps your issue
you should take a delegate back to viewController that contains current view, and call navigationController.push from there

iOS pushViewController not navigating to controller in Swift5

I am having issues using pushViewController in Swift5, I have searched StackOverflow for answers & could not find any one that works.
All I'm trying to do is navigate to another controller using pushViewController.
Using self.present works for Navigation but pushViewController does not work, for reasons I do not know.
ONLY Using present works below:
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let viewController =
storyBoard.instantiateViewController(withIdentifier: "ViewController") as! ViewController
self.present(viewController, animated: true, completion: nil)
But using pushViewController never works:
I tried this: I doesn't work
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "ViewController") as! ViewController
navigationController?.pushViewController(vc, animated: true)
I tried this: I doesn't work too
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "ViewController" )
var navigationController = UIApplication.shared.keyWindow?.rootViewController as! UINavigationController
navigationController.pushViewController(viewController, animated: true)
I tried this, It also doesn't work
let viewController = storyboard.instantiateViewController(withIdentifier: "ViewController" )
let vc = self.windowRootViewController() as! ViewController
let nvc = vc.parent as! UINavigationController
nvc.pushViewController(viewController, animated: true)
Please can someone guide me properly on what I'm doing wrong or checklist or configuration I need to do for this to work?
Thanks everyone!
Set breakpoint in your code and check whether navigationController is not nil. If it is nil, pushViewController will not work.
Since you are able to present the viewController, instantiating itt using "ViewController" should not be an issue.
The ViewController which try to push must be embedded into NavigationController.
Assume you have two ViewControllers - ViewControllerA and ViewControllerB.
In order to push ViewControllerB from ViewControllerA, The ViewControllerA must be embedded into NavigationController.
So that you can push ViewControllerB to the navigation stack.
If ViewControllerA is not embedded into NavigationController It's navigationController property will be nil. So you will not be able to push ViewControllerB.

Load all views related to tab bar controller by hard code

I would like to jump from a viewController to the first viewController related to Tab Bar Controller through code.
The tabBarController Scene has storyboard id tabView.
I'm working on this way:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc: UITabBarController!
storyboard.instantiateViewController(withIdentifier: "tabView")
vc=storyboard.instantiateViewController(withIdentifier: "tabView") as! UITabBarController
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.present(vc as! UIViewController, animated: true, completion: nil)
}
But it loads only the first viewController (out of 5) without the tab bar related to. How can I solve it?
Oh, this code looks so wrong.
In your storyboard give and "tabView" ID to the TabBarController, not the ViewController inside it.
Why you are double instantiating ViewController? just do it once and assign it to the vc variable.
Why you've created delay before presenting the VC? It's some sort of workaround of something?
Working code:
let vc = storyboard.instantiateViewController(withIdentifier: "tabView") as! UITabBarController
self.present(vc, animated: true)
Use
(1)if you want to navigate from Appdelegate
let appDelegate = UIApplication.sharedApplication.delegate as! AppDelegate
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let tabBar = mainStoryboard.instantiateViewControllerWithIdentifier("TabBarController") as! TabBarController
appDelegate.window?.rootViewController = tabBar
appDelegate.window?.makeKeyAndVisible()
(2)if you want to navigate from viewcontroller which has root of navigation
self.navigationController?.pushViewController(tabBar, animated: true)

How to call another Storyboard as a popover?

Assumed there is a 'ViewControllerOne' in Storyboard 'A'. If a user tapped a button on it, 'ViewControllerOne' will call Storyboard 'B' and show it as a popover on the screen. It seems that I can't find any references for my problem.
I would like to call another Storyboard from a Storyboard and show it as a popover, is it possible to do this? Thank you.
EDIT
I've tried the solution provided by #Sohil R. Memon, but I got an error :
reason: 'Storyboard (<UIStoryboard: 0x7fe69a841f00>) doesn't contain a view controller with identifier 'PaymentOnly''
I've added the RestorationID to the View Controller.
But if I change the code to :
let storyBoard : UIStoryboard = UIStoryboard(name: "PaymentOnly", bundle:nil)
let navigationController: UINavigationController = storyBoard.instantiateInitialViewController() as! UINavigationController
let viewController = navigationController.viewControllers[0] as! PaymentOnlyViewController
self.navigationController?.pushViewController(viewController, animated: true)
It worked but doesn't pop over the view. Below is the code from #Sohil R. Memon :
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "PaymentOption" {
let storyBoard = UIStoryboard(name: "PaymentOnly", bundle: nil)
let vc = self.storyboard!.instantiateViewControllerWithIdentifier("PaymentOnly") as! PaymentOnlyViewController
self.presentViewController(vc, animated: false, completion: nil)
}
}
You can obviously present / popover any of the UIViewController from anywhere in any UIStoryBoard.
Expecting this is your first UIViewController and you want to call any other UIViewController from other UIStoryBoard. So for that find the below code:
let storyBoard = UIStoryboard(name: "storyboard_name", bundle: nil)
let vc = self.storyboard!.instantiateViewControllerWithIdentifier("chatVC") as! ChatVC
self.presentViewController(vc, animated: false, completion: nil)
This way you can present or push any of the UIViewController.
Popover reference link.

Go to a nested ViewController from a main TabBarController programmatically in Swift

I have the following ViewController structure, see image below.
Whenever I want to move from ViewController 1 to any of the other main controllers I use self.tabBarController?.selectedIndex = indexNumber
// for instance, this would take me to ViewController 3
self.tabBarController?.selectedIndex = 2
Based on the picture below, how can I go from ViewController 1 to TargetViewController programmatically when a button is tapped in ViewController 1?
FYI -
In the picture below I'm showing a button in ViewController 3 this is just to show the storyboard structure, the actual button-tap will happen in ViewController 1
EDIT:
Here is how you do it based on Prashant Tukadiya's answer.
ViewController 1
In ViewController 1 add the following in your tap event.
self.tabBarController?.selectedIndex = 2
let nav = (self.tabBarController?.viewControllers?[2] as? UINavigationController)
let vc = TargetViewController.viewController()
nav?.pushViewController(vc, animated: true)
TargetViewController
In your TargetViewController add the following class method.
class func viewController() -> TargetViewController {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
return storyboard.instantiateViewController(withIdentifier: "targetViewControllerID") as! TargetViewController
}
Add targetViewControllerID in the Storyboard ID field.
I was facing same before a couple of days and finally, I got a solution maybe this will help you.
TabController.shared.tabcontroller.selectedIndex = 1
let navigation = TabController.shared.tabcontroller.selectedViewController?.navigationController
let SavedAddress = self.storyboard?.instantiateViewController(withIdentifier: "SavedAddressVC") as! SavedAddressVC
navigation?.pushViewController(SavedAddress, animated: true)
I have used the same solution. and this is the working code for me.
You can directly give identifier to the TargetViewController from storyboard and load from storyboard then and push or present it.
like add this method in your TargetViewController
class func viewController () -> TargetViewController {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
return storyboard.instantiateViewController(withIdentifier: "yourIdentifer") as! TargetViewController
}
and on tap event
let vc = TargetViewController.viewController()
self.navigationController?.pushViewController(vc, animated: true)
EDIT
After reading comments got clear idea about your requirements
On button action from ViewController1, You want to goto TargetViewController but when press back you want back to viewController 3
Select particular index first
self.tabBarController?.selectedIndex = 2
After that you need to grab UINavigationController
let nav = (self.tabBarController?.viewControllers?[2] as? UINavigationController)
then Push ViewController
let vc = TargetViewController.viewController()
nav?.pushViewController(vc, animated: true)
Note: Don't forgot add identifier to storyboard to TargetViewController and also add class func viewController () -> TargetViewController method to TargetViewController
Hope it is helpful
In action function of a button in ViewController 1 , you can use this :
func presentMethod(storyBoardName: String, storyBoardID: String) {
let storyBoard: UIStoryboard = UIStoryboard(name: storyBoardName, bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: storyBoardID)
self.definesPresentationContext = true
self.present(newViewController, animated: true, completion: nil)
}
//usage
presentMethod(storyBoardName: "Main", storyBoardID: "TargetViewController")

Resources