Programmatically navigate to another view controller/scene - ios

I got an error message during navigating from first view controller to second view controller. My coding is like this one
let vc = LoginViewController(nibName: "LoginViewController", bundle: nil)
self.navigationController?.pushViewController(vc, animated: true)
The problem is I always got this kind of error message
2014-12-09 16:51:08.219 XXXXX[1351:60b] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </var/mobile/Applications/FDC7AA0A-4F61-47E7-955B-EE559ECC06A2/XXXXX.app> (loaded)' with name 'LoginViewController''
*** First throw call stack:
(0x2efcaf0b 0x39761ce7 0x2efcae4d 0x31b693f9 0x31ac1eaf 0x3191e365 0x317fe895 0x318a930d 0x318a9223 0x318a8801 0x318a8529 0x318a8299 0x318a8231 0x317fa305 0x3147631b 0x31471b3f 0x314719d1 0x314713e5 0x314711f7 0x3146af1d 0x2ef96039 0x2ef939c7 0x2ef93d13 0x2eefe769 0x2eefe54b 0x33e6b6d3 0x3185d891 0x4ccc8 0x4cd04 0x39c5fab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)

I already found the answer
Swift 4
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "nextView") as! NextViewController
self.present(nextViewController, animated:true, completion:nil)
Swift 3
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewControllerWithIdentifier("nextView") as NextViewController
self.presentViewController(nextViewController, animated:true, completion:nil)

Try this one. Here "LoginViewController" is the storyboardID specified in storyboard.
See below
let secondViewController = self.storyboard?.instantiateViewControllerWithIdentifier("LoginViewController") as LoginViewController
self.navigationController?.pushViewController(secondViewController, animated: true)

XCODE 8.2 AND SWIFT 3.0
Present an exist UIViewController
let loginVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
self.present(loginVC, animated: true, completion: nil)
Push an exist UIViewController
let loginVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
self.navigationController?.pushViewController(loginVC, animated: true)
Remember that you can put the UIViewController Identifier following the next steps:
Select Main.storyboard
Select your UIViewController
Search the Utilities in the right
Select the identity inspector
Search in section identity "Storyboard ID"
Put the Identifier for your UIViewController

If you want to navigate to Controller created Programmatically, then do this:
let newViewController = NewViewController()
self.navigationController?.pushViewController(newViewController, animated: true)
If you want to navigate to Controller on StoryBoard with Identifier "newViewController", then do this:
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "newViewController") as! NewViewController
self.present(newViewController, animated: true, completion: nil)

Swift3:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController("LoginViewController") as UIViewController
self.navigationController?.pushViewController(vc, animated: true)
Try this out. You just confused nib with storyboard representation.

You can move from one scene to another programmatically using below code :
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let objSomeViewController = storyBoard.instantiateViewControllerWithIdentifier(“storyboardID”) as! SomeViewController
// If you want to push to new ViewController then use this
self.navigationController?.pushViewController(objSomeViewController, animated: true)
// ---- OR ----
// If you want to present the new ViewController then use this
self.presentViewController(objSomeViewController, animated:true, completion:nil)
Here storyBoardID is value that you set to scene using Interface Builder.
This is shown below :

See mine.
func actioncall () {
let loginPageView = self.storyboard?.instantiateViewControllerWithIdentifier("LoginPageID") as! ViewController
self.navigationController?.pushViewController(loginPageView, animated: true)
}
If you use presenting style, you might lose the page's navigation bar with preset pushnavigation.

Programmatically there are different ways based on different situations
load storyenter code hereboard nib file
let yourVc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "YourViewController") as! YourViewController;
self.present(yourVc, animated: true, completion: nil)
Load from xib
let yourVc = YourViewController.init(nibName: "YourViewController", bundle: nil)
self.present(yourVc, animated: true, completion: nil)
Navigate through Segue
self.performSegue(withIdentifier: "your UIView", sender: self)

let VC1 = self.storyboard!.instantiateViewController(withIdentifier: "MyCustomViewController") as! ViewController
let navController = UINavigationController(rootViewController: VC1)
self.present(navController, animated:true, completion: nil)

XCODE 9.2 AND SWIFT 3.0
ViewController to NextViewcontroller without Segue Connection
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "NextViewController") as! NextViewController
self.navigationController?.pushViewController(nextViewController, animated:true)
or
let VC:NextViewController = storyboard?.instantiateViewController(withIdentifier: "NextViewController") as! NextViewController
self.navigationController?.pushViewController(VC, animated: true)

You can do navigation between view controllers using code with the help of storyboard and storyboardId of the view controller.
This code is for Swift 3:
let signUpVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SignUp")
self.navigationController?.pushViewController(signUpVC, animated: true)

In addition to the good answers above to set the navigation view controller on top of your screen on your app, you can add it to your AppDelegate.swift file inside the block as follows
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow()
window?.makeKeyAndVisible()
window?.rootViewController = UINavigationController(rootViewController: LoginViewController())
return true
}

let vc = DetailUserViewController()
vc.userdetails = userViewModels[indexPath.row]
self.navigationController?.pushViewController(vc, animated: true)

I'm not sure try below steps,i think may be error occurs below reasons.
you rename some files outside XCode. To solve it remove the files from your project and re-import the files in your project.
check and add missing Nib file in Build phases->Copy bundle resources.finally check the nib name spelling, it's correct, case sensitive.
check the properties of the .xib/storyboard files in the file inspector ,the property "Target Membership" pitch on the select box,then your xib/storyboard file was linked with your target.
such as incorrect type of NIB.Right click on the file and click "Get Info" to verify that the type is what you would expect.

I Give you my code to make a transition.
In this example the action is connecting to an UIButton. So don't forget to set it.
Don't forget to set the name of your ViewController in the transition method.
Don't forget to set your storyboard too. Your need to have one view per viewController. Connect each ViewController to each view in storyBoard. You can see on the screenshoot bellow
class PresentationViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var playButton = UIButton.buttonWithType(UIButtonType.System) as UIButton
let image = UIImage(named: "YourPlayButton") as UIImage?
playButton.frame = CGRectMake(0, 0, 100, 100)
playButton.center = CGPointMake(self.view.frame.width/2, self.view.frame.height/2)
playButton.addTarget(self, action: "transition:", forControlEvents: UIControlEvents.TouchUpInside)
playButton.setBackgroundImage(image, forState: UIControlState.Normal)
self.view.addSubview(playButton)
}
func transition(sender:UIButton!)
{
println("transition")
let secondViewController = self.storyboard?.instantiateViewControllerWithIdentifier("YourSecondViewController") as UIViewController
let window = UIApplication.sharedApplication().windows[0] as UIWindow
UIView.transitionFromView(
window.rootViewController!.view,
toView: secondViewController.view,
duration: 0.65,
options: .TransitionCrossDissolve,
completion: {
finished in window.rootViewController = secondViewController
})
}
}

If you are building UI without drag and drop (without using storyboard)
and want to navigate default page or ViewController.swift to another page?
Follow these steps
1) add a class (.swift)
2) Import UIKit
3) Declare class name like
class DemoNavigationClass :UIViewController{
override func viewDidLoad(){
let lbl_Hello = UILabel(frame: CGRect(x:self.view.frame.width/3, y:self.view.frame.height/2, 200, 30));
lbl_Hello.text = "You are on Next Page"
lbl_Hello.textColor = UIColor.white
self.view.addSubview(lbl_Hello)
}
}
after creating second page come back to first page (ViewController.swift)
Here make a button in viewDidLoad method
let button = UIButton()
button.frame = (frame: CGRect(x: self.view.frame.width/3, y: self.view.frame.height/1.5, width: 200, height: 50))
button.backgroundColor = UIColor.red
button.setTitle("Go to Next ", for: .normal)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
self.view.addSubview(button)
now define buttonAction method outside of viewDidLoad() in same class
func buttonAction(sender: UIButton!)
{
let obj : DemoNavigationClass = DemoNavigationClass();
self.navigationController?.pushViewController(obj, animated: true)
}
Keep one thing that i forget
in main.storyboard there is a scene with a arrow,
select that arrow and press delete button
now drag and drop a navigationcontroller and delete tableview which comes with navaigation controller.
select navigationcontroller press control on keyboard and drag it in to another scene on storyboard that is ViewController.
This mean that your viewcontroller become root viewcontroller
hope this help you
Thanks
in main.storyboard , drag and drop navigationcontroller,

let signUpVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SignUp")
// self.present(signUpVC, animated: false, completion: nil)
self.navigationController?.pushViewController(signUpVC, animated: true)

Swift 4.0.3
#IBAction func registerNewUserButtonTapped(_ sender: Any) {
print("---------------------------registerNewUserButtonTapped --------------------------- ");
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "RegisterNewUserViewController") as! RegisterNewUserViewController
self.present(nextViewController, animated:true, completion:nil)
}
Change our Controller Name RegisterNewUserViewController

I think you are looking for something like this:
let signUpViewController = SignUpViewController()
present(signUpViewController, animated: true, completion: nil)
If you want full screen of the new page:
present(signUpViewController, animated: true, completion: nil)
Hope this helps :)

Related

How can I switch programmatically between view controllers that are not on the same storyboard?

I am trying to switch between a view controller (that is coded programmatically) to a ViewController with the UI Elements on the storyboard.
I am trying to switch between a HomeController to a TabBarController using a button but by pressing the button it switches to a dark screen. I would be glad if some of you could help me out.
Here is my code:
var welcomeLabel: UIButton = {
let label = UIButton()
label.tintColor = .white
label.translatesAutoresizingMaskIntoConstraints = false
label.alpha = 0
label.addTarget(self, action: #selector(handleLogin), for: .touchUpInside)
return label
}()
...............
#objc func handleLogin() {
navigationController?.show(TabBarController(), sender: Any?.self)
}
use this code if you're pushing view from NavigationController
navigationController?.pushViewController("YourViewController", animated: true)
You can do it in following way
let storyboard = UIStoryboard(name: "Your_storyboard", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "Your_View_controller") as! Your_View_controller
Now to present
self.present(viewController, animated: true, completion: nil)
Or through navigation controller
navigationController?.pushViewController(viewController, animated: true)
You can try this -
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil) // Give the name .e.g if you have the different story board name
let YourNextViewController = storyBoard.instantiateViewController(withIdentifier: "your story board identifier") as! StoryBoardName/ClassName
self.navigationController?.pushViewController(YourNextViewController, animated: true)
//Or if you want to present viewController
self.present(YourNextViewController, animated:true, completion:nil)

Dismiss a viewController after using a push method

I use this function to push a new viewController:
func goToPasscodeSetupVC() {
let storyboard = UIStoryboard(name: "PassCode", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "passcodeSetupVC") as! PasscodeSetupVC
self.navigationController?.pushViewController(viewController, animated: true)
}
But, when I am on the new viewController, I want to dismiss the previous one so that I could't reach it with a swipe gesture.
You can use this to disable swipe back gesture.
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
You can try setViewControllers instead of pushViewController
let storyboard = UIStoryboard(name: "PassCode", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "passcodeSetupVC") as! PasscodeSetupVC
self.navigationController?.setViewControllers([viewController], animated: true)

How do I present a new UIViewController when Storyboard Refrences are used

So I am using some Storyboard References to bring in some structure. Now I am trying to change the ViewController from code, but I am not able to use a ViewController from a different Storyboard. My Code is currently looking like that:
func showCommunityDetail(){
let storyBoard : UIStoryboard = UIStoryboard(name: "community", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "communityDetail") as! CommunityViewController
self.present(nextViewController, animated:true, completion:nil)
}
The community Storyboard contains the communityDetail controller, but the view which is shown at the moment this code is executed, is in a different storyboard.
How can I present between different Storyboards?
Update
I updated my code to the following line:
let detailViewController = UIStoryboard(name: "community", bundle: nil).instantiateViewController(withIdentifier: "communityDetail");
However, now i get a new error: whose view is not in the window hierarchy!
To present a view controller in a different storyboard.
1) Make sure the "Initial View Controller" property is set for the entry ViewController in each of the storyboards.
Present it:
let vcToPresent = UIStoryboard(name: "StoryboardName", bundle: nil).instantiateInitialViewController();
// Ensure its of the type that you want, so that you can pass info to it
guard let specialVC = vcToPresent as? SpecialViewController else {
return
}
specialVC.someProperty = somePropertyToPass
self.present(specialVC, animated: true, completion: nil)
Edit:
To instantiate a different viewcontroller (other than the one who is marked as initial) the following method can be used:
func instantiateViewController(withIdentifier identifier: String) -> UIViewController
Link to the documentation: https://developer.apple.com/reference/uikit/uistoryboard/1616214-instantiateviewcontroller
Note that you MUST set an identifier on the interface builder for the viewcontroller you want to use this method with.
Just worked on the requirement you asked for and it is in swift 2.2. Try it out it works this way.
var nextViewController : CommunityViewController!
func showCommunityDetail() {
let mainStoryboard = UIStoryboard(name: "community", bundle: nil)
nextViewController = mainStoryboard.instantiateViewControllerWithIdentifier("communityDetail") as! CommunityViewController
addChildViewController(nextViewController)
// Optionally you can change the frame of the view controller to be added
nextViewController.view.frame = CGRect(x: 0, y: 0 , width: view.frame.width, height: view.frame.height)
view.addSubview(nextViewController.view)
nextViewController.didMoveToParentViewController(self)
}

How to move to another UINavigationViewController using swift?

How to i segue over to another UINavigationViewcController programmatically so there is a back button to go to the previous screen. I tried using this code, but it just models over.
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let resultViewController = storyBoard.instantiateViewControllerWithIdentifier("NavViewController") as FirstMemberViewController
self.presentViewController(resultViewController, animated:true, completion:nil)
Try this
// Your controllers
let navigationController = UINavigationController()
let viewController = UIViewController()
// The push
navigationController.pushViewController(viewController, animated: true)
I found the answer...
navigationController!.pushViewController(storyboard!.instantiateViewControllerWithIdentifier("Home") as! UIViewController, animated: true)

Go to a nested ViewController from a main TabBarController programmatically in Swift

I have the following ViewController structure, see image below.
Whenever I want to move from ViewController 1 to any of the other main controllers I use self.tabBarController?.selectedIndex = indexNumber
// for instance, this would take me to ViewController 3
self.tabBarController?.selectedIndex = 2
Based on the picture below, how can I go from ViewController 1 to TargetViewController programmatically when a button is tapped in ViewController 1?
FYI -
In the picture below I'm showing a button in ViewController 3 this is just to show the storyboard structure, the actual button-tap will happen in ViewController 1
EDIT:
Here is how you do it based on Prashant Tukadiya's answer.
ViewController 1
In ViewController 1 add the following in your tap event.
self.tabBarController?.selectedIndex = 2
let nav = (self.tabBarController?.viewControllers?[2] as? UINavigationController)
let vc = TargetViewController.viewController()
nav?.pushViewController(vc, animated: true)
TargetViewController
In your TargetViewController add the following class method.
class func viewController() -> TargetViewController {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
return storyboard.instantiateViewController(withIdentifier: "targetViewControllerID") as! TargetViewController
}
Add targetViewControllerID in the Storyboard ID field.
I was facing same before a couple of days and finally, I got a solution maybe this will help you.
TabController.shared.tabcontroller.selectedIndex = 1
let navigation = TabController.shared.tabcontroller.selectedViewController?.navigationController
let SavedAddress = self.storyboard?.instantiateViewController(withIdentifier: "SavedAddressVC") as! SavedAddressVC
navigation?.pushViewController(SavedAddress, animated: true)
I have used the same solution. and this is the working code for me.
You can directly give identifier to the TargetViewController from storyboard and load from storyboard then and push or present it.
like add this method in your TargetViewController
class func viewController () -> TargetViewController {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
return storyboard.instantiateViewController(withIdentifier: "yourIdentifer") as! TargetViewController
}
and on tap event
let vc = TargetViewController.viewController()
self.navigationController?.pushViewController(vc, animated: true)
EDIT
After reading comments got clear idea about your requirements
On button action from ViewController1, You want to goto TargetViewController but when press back you want back to viewController 3
Select particular index first
self.tabBarController?.selectedIndex = 2
After that you need to grab UINavigationController
let nav = (self.tabBarController?.viewControllers?[2] as? UINavigationController)
then Push ViewController
let vc = TargetViewController.viewController()
nav?.pushViewController(vc, animated: true)
Note: Don't forgot add identifier to storyboard to TargetViewController and also add class func viewController () -> TargetViewController method to TargetViewController
Hope it is helpful
In action function of a button in ViewController 1 , you can use this :
func presentMethod(storyBoardName: String, storyBoardID: String) {
let storyBoard: UIStoryboard = UIStoryboard(name: storyBoardName, bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: storyBoardID)
self.definesPresentationContext = true
self.present(newViewController, animated: true, completion: nil)
}
//usage
presentMethod(storyBoardName: "Main", storyBoardID: "TargetViewController")

Resources