Access view controller from referencing storyboard - ios

As I know that referencing storyboard can be used to make the multiple storyboard with the same storyboard reference. If all View Controllers hierarchy is connected via the segue it works.
I want to know how to use referencing storyboard without segue between View controllers, because one view controller may be used in multiple ways or may need to access the view controller with the storyboard identifier from the new referencing storyboard.
Please let me know, I want to use referencing storyboard's view controller without the segue.

You could do somthing like this...
#IBAction func tapButtonToShowOtherController(_ sender: Any?) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
//storyboard identifier set in storyboard "userSB"
let aVC = storyboard.instantiateViewController(withIdentifier: "userSB") as? AViewController
aVC?.udelegate = self
self.present(aVC!, animated: true, completion: nil)
}

Give the id to storyboard in identity inspecter like "ViewController_id"
MyCartViewController* destVC = [self.storyboard instantiateViewControllerWithIdentifier:#"MyCartViewController_id"];
[self.navigationController pushViewController:destVC animated:YES];

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
MyNewViewController *myVC = (MyNewViewController *)[storyboard instantiateViewControllerWithIdentifier:#"myViewCont"];

Select your viewcontroller from storyboard and select identity inspecter give stoary board id whatever you want
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"your storyboard name" bundle:nil];
MyNewViewController *myVC = (MyNewViewController *)[storyboard instantiateViewControllerWithIdentifier:#"your storyboard id"];
I downloaded sample at here https://www.raywenderlich.com/115697/ios-9-storyboards-tutorial-whats-new-in-storyboards
They have used storyboard reference as segue.Here i have modified something below:
1.select Checklists.stoaryboard
2.Remove ChecklistDetailViewController segue.
3.Select ChecklistsViewController.swift
4.Add following code:Its working without segue
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let storyboard = UIStoryboard(name: "ChecklistDetail", bundle: nil)
let aVC = storyboard.instantiateViewController(withIdentifier: "ChecklistDetailViewController") as? ChecklistDetailViewController
aVC?.checklist = checklists[indexPath.row]
navigationController?.pushViewController(aVC!, animated: true)
}
5.comment prepare(for segue: UIStoryboardSegue, sender: Any?) method.
Here i have understand:
When you are using, storyboard reference You need to mention ReferenceID
Then you can take viewcontroller by giving stoarboard name with Respective storyboardId

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

How do i pass a json response from one view controller to another view controller in a different storyboard

How do I pass the json response I received from api to another viewcontroller in a different storyboard ?
I tried using segues but doesn't seem to work
let propass = UIStoryboard(name: "ProfileStoryboard", bundle: Bundle.main).instantiateViewController(withIdentifier: "ProfileViewController") as! ProfileViewController
propass.proDict2 = parseJSON2
Try to add:
self.present(propass, animated: true, completion: nil)
after:
propass.proDict2 = parseJSON2
If you set up segues through the storyboard, then it makes sense that it didn't work through the segue when you tried the code above. The issue is that when when you set up a storyboard segue, the App deals with creating a new VC and presenting/showing it from your original VC.
What you are doing in your code, is that you are instantiating a new version of the same view controller, which is not the one being shown/presented.
You have 2 ways to implement this, firstly it is by overriding prepareForSegue in the ViewController that shows/presents your propass View Controller:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "YOUR SEGUE IDENTIFIER FROM THE STORYBOARD" {
let propassVC = segue.destination as! ProfileViewController
propassVC.proDict = parseJSON2
}
}
Another way to implement this, is to remove the segue you set up in the storyboard. Then you do as you are doing to initialize the Propass VC and to pass data to it.
let propassStoryboard = UIStoryboard(name: "Main", bundle: nil)
let propassVC = propassStoryboard.instantiateViewController(withIdentifier: "PROPASS IDENTIFIER SET IN STORYBOARD") as ProfileViewController
propassVC.jsonDict = JSONParse2
show(propassVC, sender: 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.

How can I load storyboard programmatically from class?

My problem is that I was looking for way to use both storyboard and xib. But I can't find proper way to load and show storyboard programmatically. Project was started developing with xib, and now it's very hard to nest all xib files in storyboard. So I was looking a way to do it in code, like with alloc, init, push for viewControllers. In my case I have only one controller in storyboard: UITableViewController, which has static cells with some content I want to show. If anyone knows proper way to work both with xib and storyboard without huge refactoring, I will appreciate for any help.
In your storyboard go to the Attributes inspector and set the view controller's Identifier. You can then present that view controller using the following code.
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"myViewController"];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];
Swift 3
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "viewController")
self.navigationController!.pushViewController(vc, animated: true)
Swift 2
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("viewController")
self.navigationController!.pushViewController(vc, animated: true)
Prerequisite
Assign a Storyboard ID to your view controller.
IB > Show the Identity inspector > Identity > Storyboard ID
Swift (legacy)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("viewController") as? UIViewController
self.navigationController!.pushViewController(vc!, animated: true)
Edit: Swift 2 suggested in a comment by Fred A.
if you want to use without any navigationController you have to use like following :
let Storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = Storyboard.instantiateViewController(withIdentifier: "viewController")
present(vc , animated: true , completion: nil)
In attribute inspector give the identifier for that view controller and the below code works for me
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
DetailViewController *detailViewController = [storyboard instantiateViewControllerWithIdentifier:#"DetailViewController"];
[self.navigationController pushViewController:detailViewController animated:YES];
Try this
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"Login"];
[[UIApplication sharedApplication].keyWindow setRootViewController:vc];
in swift
NavigationController and pushController you can replace for
present(vc, animated:true , completion: nil)
For swift 4 and 5, you can do this. Good practice is set name of Storyboard equal to StoryboardID.
enum StoryBoardName{
case second = "SecondViewController"
}
extension UIStoryboard{
class func load(_ storyboard: StoryBoardName) -> UIViewController{
return UIStoryboard(name: storyboard.rawValue, bundle: nil).instantiateViewController(withIdentifier: storyboard.rawValue)
}
}
and then you can load your Storyboard in your ViewController like this:
class MyViewController: UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
guard let vc = UIStoryboard.load(.second) as? SecondViewController else {return}
self.present(vc, animated: true, completion: nil)
}
}
When you create a new Storyboard just set the same name on StoryboardID and add Storyboard name in your enum "StoryBoardName"
You can always jump right to the root controller:
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [storyboard instantiateInitialViewController];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];
The extension below will allow you to load a Storyboard and it's associated UIViewController. Example: If you have a UIViewController named ModalAlertViewController and a storyboard named "ModalAlert" e.g.
let vc: ModalAlertViewController = UIViewController.loadStoryboard("ModalAlert")
Will load both the Storyboard and UIViewController and vc will be of type ModalAlertViewController. Note Assumes that the storyboard's Storyboard ID has the same name as the storyboard and that the storyboard has been marked as Is Initial View Controller.
extension UIViewController {
/// Loads a `UIViewController` of type `T` with storyboard. Assumes that the storyboards Storyboard ID has the same name as the storyboard and that the storyboard has been marked as Is Initial View Controller.
/// - Parameter storyboardName: Name of the storyboard without .xib/nib suffix.
static func loadStoryboard<T: UIViewController>(_ storyboardName: String) -> T? {
let storyboard = UIStoryboard(name: storyboardName, bundle: nil)
if let vc = storyboard.instantiateViewController(withIdentifier: storyboardName) as? T {
vc.loadViewIfNeeded() // ensures vc.view is loaded before returning
return vc
}
return nil
}
}

Resources