How to push a new view controller from a view - ios

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

Related

How can i pop back from storyboard of framework?

let storyboardBundle = Bundle(identifier: "SignUPFramework")
let vc = UIStoryboard.init(name: "SignIn", bundle: storyboardBundle).instantiateViewController(withIdentifier: "SignInViewcontroller") as! SignInViewcontroller
navigationController?.pushViewController(vc, animated: true)
I have navigated to storyboard of framework as above.
You own the navigationController. So you can use either popViewController(animated:) (if you are sure that there is only one view controller you wish to pop), or popToViewController(_:animated:), or popToRootViewController(animated:) (if you wish to return to the root).
It does not matter that the storyboard is in a framework. You still own the view hierarchy, the navigation stack and the view controller instance you get from the below line of code
let vc = UIStoryboard.init(name: "SignIn", bundle: storyboardBundle).instantiateViewController(withIdentifier: "SignInViewcontroller") as! SignInViewcontroller
So you can do whatever you want with it in terms of navigation (push it and pop it or present it and dismiss it).
You just need to identify at what point you want to trigger any of these actions.
I think you are using xib so it will not return action first you should do protocol for callback to view controller then you can use popViewController(animated:).
protocol CallBackDelegate: AnyObject {
func back()
}
//Delegate
weak var delegate:CallBackDelegate?
#IBAction func buttonAction(_ sender: Any) {
delegate?.back()
}
Now you can use protocol in view controller
class ViewController: UIViewController, CallBackDelegate {
func back() {
navigationController?.popViewController(animated: true)
}
}
Note :- Confirm delegate variable in cellForRowAtIndexPath i.e.
cell.delegate = self
I have solved it by
let bundle = Bundle(for: SignInViewcontroller.self)
let vc = UIStoryboard.init(name: "SignIn", bundle: bundle).instantiateViewController(withIdentifier: "SignInViewcontroller") as! SignInViewcontroller
in above snippet instead of passing bundle id i have passed viewcontroller itself.

ios swift - instantiating same VC from multiple tabs

I have multiple tabs connected via separate navigation controllers. I want to to instantiate same End Pt VC, irrespective of which tab user chooses tabs 1 through 4.
When I select Tab 1 it shows End Pt VC because it is connected via Segue. However when I select other tabs I manually try to push EndPt VC as shown in the tab controller method. But it shows blank screen. How can I present the same End Pt VC irrespective of tab selection?
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
if let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "EndPointTVC") as? EndPtListTableViewController{
viewController.selectedTab = self.selectedTab
if let navigator = self.navigationController {
navigator.pushViewController(viewController, animated: true)
}
}
}
You can detect when the UITabBarController changes tab via its delegate UITabBarControllerDelegate. In the following delegate method, you can cast the selected view controller to a UINavigationController (which is what I can make out in the screenshot you attached).
extension MyTabBarController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
let myVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "MyViewControllerStoryID") as! MyViewController
let navController = viewController as! UINavigationController
navController.viewControllers = [myVC]
print(viewController)
}
}
Now, no matter which tab you choose, a new MyViewController instance is created. Even hitting the same tab multiple times will replace the current instance for a new MyViewController instance.
Try to instantiate the viewcontroller from the storyboard and then present it. Also, make sure that you have given the target viewcontroller the storyboard Id "EndPointTVC" in the Identify section.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier : "EndPointTVC")
viewController.selectedTab = self.selectedTab
self.present(viewController, animated: true)

Push another Viewcontroller from action button in xib file

I have a viewcontroller that presents from a .xib.
Inside the .xib there is a button; I want the button to pushviewcontroller to an other viewcontroller (ViewControllerPeopleNew).
I use an action button:
#IBAction func _hitPeople(sender: AnyObject) {
let mapViewControllerObejct = self.storyboard?.instantiateViewControllerWithIdentifier("peoplenew") as? ViewControllerPeopleNew
self.navigationController?.pushViewController(mapViewControllerObejct!, animated: false)
}
But got an error:
Signal SIGABRT
unrecognized selector sent to instance
I already checked all about name identifier viewcontroller and all is right.
From view controller present with XIB you can not get storyboad use below code
#IBAction func _hitPeople(sender: AnyObject) {
let storyboard = UIStoryboard(name: "storyboadname", bundle: nil)
let mapViewControllerObejct = storyboard.instantiateViewControllerWithIdentifier("peoplenew") as? ViewControllerPeopleNew
self.navigationController?.pushViewController(mapViewControllerObejct!, animated: false)
}
Always remember that you can only use self.storyBoard to instantiate a view controller when both the view controllers (To and From view controllers) belong to the same storyboard. If not then you need to first get a reference to the storyboard your To view controller belongs to. So you need to do this:
#IBAction func _hitPeople(sender: AnyObject) {
let stotyboard = UIStoryboard(name: "YourStoryboard", bundle: nil)
let mapViewControllerObejct = storyboard?.instantiateViewControllerWithIdentifier("peoplenew") as? ViewControllerPeopleNew
self.navigationController?.pushViewController(mapViewControllerObejct!, animated: false)
}
PS: Just be sure that your From view controller is in the navigation stack i.e. self.navigationController is not nil.

Segue to Another Storyboard Swift

I am attempting to segue to another storyboard programmatically, but every time I've tried the view loads with a black screen with no content.
Here's the code I've been working with:
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let startingView = storyboard.instantiateViewControllerWithIdentifier("HomeScreenView")
self.showViewController(startingView, sender: self)
I've created the reference on the Origin's Storyboard of the Destination Storyboard and have also tried to call:
performSegueWithIdentifier("changeover", sender: self)
Any thoughts and suggestions would be greatly appreciated.
I've haven't had issues using Storyboard References with segues. Here are the steps I've followed to get it working:
1) In the storyboard with the source view controller, drag a storyboard reference onto the canvas.
2) Set the reference to point to the correct storyboard name and view controller in the attribute inspector
3) Ctrl+drag from the source's view controller icon (in the top bar of the scene) to the storyboard reference in order to create a segue.
4) Set the segue to "Show" and give it the identifier "Test" in the attribute inspector
5) In your source view controller's code, at the appropriate location where you want it triggered, add the line:
performSegueWithIdentifier("Test", sender: self)
That should be everything needed for the segue to be called programmatically!
"MyStoryBoard" this is the storyboard name where you want to go
"StoryboardId" this is the controller id which i want to show after segue.
let storyboard = UIStoryboard(name: "Service", bundle: nil)
let myVC = storyboard.instantiateViewController(withIdentifier: "ProfileTimelineVC") as! ProfileTimelineVC
self.present(myVC, animated: true, completion: nil)
In AppDelegate append var window: UIWindow?
let storyboard = UIStoryboard(name: "Registration", bundle: nil)
let registrationvc = storyboard.instantiateViewController(withIdentifier:
"RegistrationViewController") as! RegistrationViewController
self.window?.rootViewController?.present(registrationvc, animated: true,
completion: nil)

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.

Resources