Programmatically Segue Between Views in Different Storyboard Files - swift

I have a view HostViewController in Host.storyboard and, in storyboard I am able to segue to AttendDetailViewController in Main.storyboard. However, I want to do this programmatically as follows:
private func attendDetailViewControllerSegue(event: CAEvent) {
let vc = AttendDetailViewController(nibName: "AttendDetailViewController", bundle: nil)
vc.event = event
navigationController?.pushViewController(vc, animated: true)
}
However, when I run this I get the following error:
'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle ... with name 'AttendDetailViewController''
I have tried every solution on the internet for this problem, and I feel it might have something to do with the Views being in different storyboards.
Any thoughts on how to do this segue without an exception?

You have to get the storyboard from the bundle:
var hostStoryboard = UIStoryboard(name: "Host", bundle: Bundle.main)
Then, instantiate and present the view controller:
let someViewController = hostStoryboard?.instantiateViewController(withIdentifier: "AttendDetailViewController") as? AttendDetailViewController
self.navigationController?.present(attendDetailViewController!, animated: true)
Don't forget to set the AttendDetailViewController's storyboard identifier in the storyboard.
I also recommend you safely unwrap attendDetailViewController before using it:
let someViewController = hostStoryboard?.instantiateViewController(withIdentifier: "AttendDetailViewController") as? AttendDetailViewController
if let vc = attendDetailViewController {
self.navigationController?.present(vc, animated: true)
}

1- to load from xib ( used when there is AttendDetailViewController.xib file in your project )
let vc = AttendDetailViewController(nibName: "AttendDetailViewController", bundle: nil)
2- to load from storyboard ( used when the vc is inside a storyboard )
let vc = UIStoryboard(name: "Host", bundle: nil)!.instantiateViewController(withIdentifier: "vciD") as? AttendDetailViewController
3- load programmatically ( used when the vc layout is created programmatically )
let vc = AttendDetailViewController()

Related

EXC_BAD_ACCESS when using instantiateViewController

I'm trying to make a Home Screen Quick action to open a specific view controller, when I run the app I get a Thread 1: EXC_BAD_ACCESS (code=261, address=0xdac11530) error on the line shown below. Any ideas as to solve this?
func navigateToMoreDoggosVC() {
let storyBoard = UIStoryboard.init(name: "Main", bundle: nil)
let moreDoggosVC = storyBoard.instantiateViewController(withIdentifier: "moreDoggosViewController") //Thread 1: EXC_BAD_ACCESS (code=261, address=0x********)
let navVC = self.window?.rootViewController as? UINavigationController
navVC?.pushViewController(moreDoggosVC, animated: true)
}
if you need any more info i would be happy to edit the question.
You can't push a view controller on launching the app.
You need to set a rootViewController and then make it makeKeyAndVisible.
How can we achieve this see below code:
func navigateToMoreDoggosVC() {
let storyBoard = UIStoryboard.init(name: "Main", bundle: nil)
let moreDoggosVC = storyBoard.instantiateViewController(withIdentifier: "moreDoggosViewController")
window?.rootViewController = UINavigationController(rootViewController: moreDoggosVC)
window?.makeKeyAndVisible()
}
You need to add this code in the SceneDelegate.swift file and call it from the willConnectTo function.

Unable to complete the operation while pushing a new controller

I am trying to navigate into a new controller, but I am getting the following error:
error The operation couldn’t be completed. (placesapi error 16.)
I have tried a couple of ways to do it, but the error persists.
Attemp1
self.navigationController?.pushViewController(MainViewController(), animated: true)
Attemp2
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let mainViewController = storyBoard.instantiateViewController(withIdentifier: "mainViewControllerID") as! MainViewController
self.present(mainViewController, animated: true, completion: nil)
The identifier of the controller is set as the image shows:
Solve
After cleaning my project and changing the name of the navigationController as Frankenstein mentioned, the navigation works. Note that cleaning was required.
You need to give the story-board name and not the view-controller name:
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let mainViewController = storyBoard.instantiateViewController(withIdentifier: "mainViewControllerID") as! MainViewController
Edit: Make sure your Main.storyboard file has a ViewController whose class is set as MainViewController and identifier is set as "mainViewControllerID"

Do I use storyboards right?

Am I using storyboards right?
I have several storyboards with view controllers in them.
When I need to navigate between them, I do the following:
I do create a new instance of the storyboard let storyboard = ... every time I use them. Is this a bad method? Or Should I declare it in the view did load?
func detailsRequestedForMessage(message: message) {
let storyboard = UIStoryboard(name: "Additional", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "MessageDetailsViewController") as! MessageDetailsViewController
viewController.messageId = message.id
self.navigationController?.pushViewController(viewController, animated: true)
}
func viewAllMessage() {
let storyboard = UIStoryboard(name: "Additional", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "AllMessageViewController") as! AllMessageViewController
self.navigationController?.pushViewController(viewController, animated: true)
}
func viewOptions() {
let storyboard = UIStoryboard(name: "Options", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "OptionsViewController") as! OptionsViewController
self.present(viewController, animated: true)
}
It costs nothing to store a storyboard reference, but takes time to resolve a storyboard reference from a name. So I would say that you should put lines like
self.storyboardAdditional = UIStoryboard(name: "Additional", bundle: nil)
in viewDidLoad, storing the references in properties, and thereafter refer to the storyboards by way of the properties.

Show view controller from main storyboard

I have a case in one of my Swift files which runs the following method:
case .editProfile:
vc = PoiDetailViewController()
self.navigationController?.popViewController(vc,animated: true)
It doesn't seem to work when I run the code.
The view controller is located on the main storyboard and I would like PoiDetailViewController to display when this case is called.
If I understand it correctly, you should be able to achieve what you're looking for by present in your code. Like so:
case .editProfile:
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyBoard.instantiateViewController(withIdentifier: "PoiDetailViewController") // or whatever identifier you have given it
self.present(vc, animated: true, completion: nil)
That should work, however, make sure you set a storyboard ID for your view controller in the identity inspector.
No segues are required.
To set up a storyboard ID click on the View Controller you would like to use (in this case, PoiDetailViewController) and click the identity inspector icon and set a storyboard ID where it asks. I have attached an image so you can see where it needs to go (in the field marked 'Storyboard ID')
Hope that helps.
As per my Understanding you need to pop to specific View Controller if it is in stack and if not then you need to push to that controller
var loginVCFound:Bool = false;
let navigationController : UINavigationController! = self.window!.rootViewController as! UINavigationController;
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil);
let viewControllers: [UIViewController] = navigationController.viewControllers
for aViewController in viewControllers {
if aViewController is LoginVC {// Pass the name of your controller here
loginVCFound = true;
navigationController.popToViewController(aViewController, animated: true)
break;
}
}
if !loginVCFound { // change the identifier and VC with yours
let objLoginVC = mainStoryboard.instantiateViewController(withIdentifier: "LoginVC") as! LoginVC
navigationController.pushViewController(objLoginVC, animated: true)
}

cannot instantiante and push to another view controller

i have collection view and if cell selected, it downloading a pdf file. After download completed and select the cell again, it push to another view controller. But it doesnt push, can someone explain why?
here's my code
if self.percentProgressFinal == 1.0 { //download complete
print("SUCCESS")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("NEXT")
self.navigationController?.pushViewController(vc, animated: true)
} else {
print("still downloading")
}
It successful printing "SUCCESS" but the code wont execute. I Also try use present and this
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let nextViewController: redirectMagazineViewController = storyBoard.instantiateViewControllerWithIdentifier("NEXT") as! redirectMagazineViewController // my second view controller name
self.navigationController?.pushViewController(nextViewController, animated: true)
and still doesnt work. I'm sure my storyboard id is "NEXT".
Seems like you don't have navigation controller embedded.
Did you check the button " use storyboard id" on your Identity Inspector view controller?