Our App should be able to go from the main storyboard to another storyboard which contains a splitViewController that leads to a searchbar.
We created the searchbar in another storyboard and connected it to the navigation controller like this:
#IBAction func artikelButton(_ sender: Any) {
let viewController = self.storyboard!.instantiateViewController(withIdentifier:"MasterViewController")
self.navigationController?.pushViewController(viewController, animated: true)
}
If you then press that button the app crashes with the SIGABRT error.
The other 2 Buttons work fine, the difference is that they are .xib files.
Here's how we made the .xib buttons:
#IBAction func infoButton(_ sender: Any) {
let vc = InfoViewController(
nibName: "InfoViewController",bundle: nil)
navigationController?.pushViewController(vc, animated: true)
}
If you load your viewcontroller from XIB. then self.storyboard will always nil.
if you are using multiple storyboard or multiple XIB's A better solution
have abstract method practice in your every viewcontroller to access from storyboard
Just like add following (change viewcontroller name and identifier as per yours )
// MARK: - Abstract Methods
public class func viewController () -> LoginVC {
return StoryBoard.main.instantiateViewController(withIdentifier: StoryBoard.controller.LoginVC) as! LoginVC
}
// Now access it with LoginVC.viewController() and do push or present whatever your operation you requred
I manage everything in constant file
public struct StoryBoard {
static let main = UIStoryboard.init(name: "Main", bundle: nil)
struct controller {
static let LoginVC = "LoginView"
}
}
Related
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.
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
In various tutorials on how to use SegmentControllers, TabBarControllers, etc. it is configured such that the variable representing the view gets its value from an instantiation of the storyboard:
private lazy var summaryViewController: SummaryViewController = {
// Load Storyboard
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
// Instantiate View Controller
var viewController = storyboard.instantiateViewController(withIdentifier: "SummaryViewController") as! SummaryViewController
// Add View Controller as Child View Controller
self.add(asChildViewController: viewController)
return viewController
}()
Why does this code not just get an instance of SummaryViewController?
Adding an instance of a VC from your Storyboard, adds all of the logic and outlets you add in the storyboard. Let's say you have the following (obviously simple) VC:
class MyVC : UIViewController {
func viewDidLoad() {
}
#IBAction buttonPressed(sender : UIButton) {
/// Do something
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "mySegue"{
var vc = segue.destinationViewController as! WhateverViewController
}
}
}
where the buttonPressed: func is connected to a button in IB, and you also have a segue with a 'mySegue' identifier. Initializing your VC from the storyboard gives you access to all of these things. You absolutely can instantiate and push a VC, without the use of the storyboard, but you should not do so, when the VC you are pushing has wired IBOutlets, IBActions, etc.... If you want to do this in code, try the following:
let myNewVC = PushedViewController()
self.navigationController?.pushViewController(myNewVC, animated : true)
This will push the myNewVC onto your navigation stack, back button and all, and without using the storyboard.
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.
I have 3(cv1, cv2, cv3) container views place on same position on mainViewContoller.
All 3 having different viewController classes (.swift)
Button is placed on cv2(secondViewController), on that button click I want to change containerView from cv2 to cv3.
For more clear, how can I call mainViewController method from secondViewController (cv2)?
secondViewController.swift
#IBAction func nextButtonClick(sender: UIButton) {
// Want to call action of firstViewController which is changeContainerView()
}
firstViewController.swift
funct changeContainerView(){
loginContainerView.hidden = true
signUpContainerView.hidden = false
}
Like that.
You should use the delegate pattern. It's very common in the Cocoa framework. See the documentation if you don't know how it works.
Try this
dispatch_sync(dispatch_get_main_queue(), { () -> Void in
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let svc = storyboard.instantiateViewControllerWithIdentifier("SecondViewController") as! SecondViewController
self.presentViewController(svc, animated: true, completion: nil)
})
Yout need just change mainstoryboard name if it needed and name of destination VC in 2 places