I have create a second view controller with a storyboard. I have specified a StoryBoard ID. I have created a class for this controller and specified this class in the story board as well:
import UIKit
import Foundation
class SecondViewController: UIViewController {
// It is really empty
}
Then I am trying to activate this controller doing quite a standard operation:
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let secondViewController = storyBoard.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
self.present(secondViewController, animated:true, completion:nil)
However, when execution reaches and invokes storyBoard.instantiateViewController - I get Thread 1: signal SIGABRT without any description (clicking on it gives nothing):
I have already looked at this QA: Swift error : signal SIGABRT how to solve it - clean & build doesn't solve the problem.
I guess I am missing something in the configuration of my second view controller. But I can not find what exactly. Any advices?
Verify your storyboard filename and use it in the line:
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
Related
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"
Want to navigate between two UIStoryBoard and between different UIViewController. My problem is that when I tap on UIButton the control should transfer to the UIViewController from current UIStoryBoard to another UIStoryBoard.
Any help is appreciated.
You can either Push or Present the new viewController
Using Following code you can push the new view controller to your navigation controller
let yourVC = UIStoryboard(name: StoryBoardName, bundle: nil).instantiateViewController(withIdentifier: ViewConrtollerID) as! YourViewController
self.navigationController?.pushViewController(yourVC, animated: true)
You first need to create reference of the second storyboard in which you want to move from current. For that you need to create reference as shown in below image and set the other story board name in that.
after that you can push the to that storyboard controller using below code.
let vc = UIStoryboard(name:"storyboadnameToPush", bundle: nil).instantiateViewController(withIdentifier:controller storyboardId)
self.navigationController?.pushViewController(vc, animated: true)
I have a HomeController and a registerController. The HomeController is embedded in a navigation controller and is the root view controller. If I present the registerController modally in HomeController's ViewWillAppear:
let reg = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "signup") as! RegisterController
reg.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
reg.modalTransitionStyle = UIModalTransitionStyle.flipHorizontal
reg.view.frame = self.view.frame
self.view.addSubview(reg.view)
There is no problem. BUT if I present it by pushing it on the navigation controller stack:
let v = RegisterController()
self.navigationController?.pushViewController(v, animated: true)
the app crashes and says the IBOutlet for the signUp button (which is in registerController) is nil. I've re-created the outlet and cleaned the project and restarted xcode and nothing has worked...
It’s not a “bug”. Your code is what’s at fault. It has nothing to do with pushing vs presenting. It’s that this line is wrong:
let v = RegisterController()
That creates a barebones view controller with no outlets hooked up. The outlets are hooked up in the storyboard instance of this class. Create the view controller from the storyboard as you did in the first code, and all will be well.
let v = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "signup") as! RegisterController
newbie here... my root view controller has the following code:
func showVC1() {
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let vc1 = storyBoard.instantiateViewController(withIdentifier: "first")
self.present(vc1, animated:true, completion:nil)
}
func showVC2() {
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let vc2 = storyBoard.instantiateViewController(withIdentifier: "second")
self.present(vc2, animated:true, completion:nil)
}
I can call these functions in either order, the first works fine, but the second will give me an error like "Attempt to present on whose view is not in the window hierarchy!"
I think I want to keep all of my code in the root vc that contains these functions. How can I make this work?
I'm also concerned that each time I call these functions I'll be creating new vc instances which will use more memory. Is there a way to keep a reference to these vc's outside of these functions? And will that solve the hierarchy issue?
Yes, second gives an error because you are trying to present two view controller at the same time from root view controller.
You can create lazy references to these view controllers
lazy var firstViewController : FirstViewController = {
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let vc1 = storyBoard.instantiateViewController(withIdentifier: "FirstViewController") as! FirstViewController
return vc1
}()
#IBAction func buttonPressed(_ sender: Any) {
self.present(firstViewController, animated:true, completion:nil)
}
Instead of presenting a new view controller try to push that one into the navigation stack like
self.navigationController.pushViewController(controller, animated: false)
Because if you present anything on your controller it will not continue the navigation. which will lead to crash
I have 3 items in my storyboard. 1. viewController (A) connected to 2. Navigation controller and 3. viewController (B) is NOT connected to anything
All 3 items have restoration identifiers set in the storyboard.
viewController (B) is the initial view controller.
I am trying in B to get the navigation controller that A is attached to, but always returns nil:
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyBoard.instantiateViewControllerWithIdentifier("viewControllerA") as! ViewControllerA
print(vc.navigationController?) // always prints nil
why!?
UPDATE#1
I can't declare a UINavigationController like a view controller. I've tried setting navigationcontroller with the id of 'myNavigationController' as storyboardID:
When storyboard, I get this error
let navigationController = storyBoard.instantiateViewControllerWithIdentifier("myNavigationController") as! UINavigationController
print(self.navigationController!) // fatal error: unexpectedly found nil while unwrapping an Optional value
I've also tried setting the id in restoration identifier, It bombed earlier at the instantiating line
#ColdLogic, see what hits I get when I search the entire project for that identifier:
Because you never instantiated the navigation controller, you instantiated view controller A. You would want something like this if you want both the nav controller and the view controller to be setup like they are in the storyboard
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let navigationController = storyBoard.instantiateViewControllerWithIdentifier("YourNavControllerIdentifier") as! UINavigationController
let vc = navigationController.topViewController as! ViewControllerA
Your code directly instantiates an object of type ViewControllerA. Which, unless you setup logic to do it, does not have a navigation controller by default.
This Worked for me!
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let navigationController = storyBoard.instantiateViewController(withIdentifier: "HomeNavigationContoller") as! UINavigationController
let viewController = storyBoard.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
navigationController.pushViewController(messageVC, animated: true)
self.present(navigationController, animated: true, completion: nil)
Use NavigationController identifier to access the NavigationController and ViewController A is already attached to it, so it will automatically get loaded to NavigationController