Segue 2 view controllers forward not working - ios

I have 3 viewControllers. viewController1 is linked to viewController2 (via segue id "first"), and viewController2 is linked to viewController3 (via segue id "destinationController"). I'm trying to segue from viewController1 to viewController3. Here is my code:
UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"DestinationController"];
[self.navigationController pushViewController:controller animated:YES];
It crashed with the following error:
'Storyboard (<UIStoryboard: 0x7fb1a944be00>) doesn't contain a view controller with identifier 'DestinationController''
How can I segue 2 viewControllers without connecting the first to the last? (I prefer not adding a segue from the storyboard because it will get very messy.)

The error is telling you that you don't have a controller with the identifier, "DestinationController". From the text in your question, it seems that you have a segue identifier called "DestinationController", but that's a different thing from an identifier on the controller, which you set in the Identity Inspector with the "Storyboard ID" field.
I think it would be more consistent though, to make a segue from the first to the third view controller. It also makes the navigation among your controllers clearer in the storyboard.

Please check "DestinationController" segue is bind with you current ViewController in which you write this code.
If you perform segue from VC1 to VC3 there is only one way in your case you have to go through VC2 (You can place conditions on viewDidLoad method of VC2 to perform segue with VC3).
Please bind "DestinationController" to your current controller and your error will gone.
This may help you :)

UIViewController3 *controller3 = [self.storyboard instantiateViewControllerWithIdentifier:#"DestinationController"];
[self.navigationController pushViewController: controller3 animated:YES];
Don't forget the set the storyboardId "DestinationController" not the segue name, Check the below Link,
Check the answer

Related

Navigate back from UITabviewController to ViewController in storyboard

My hierarchy
UINavigationController -> UIViewController
-> UITabViewController
-> ViewController1
-> ViewController2
-> ViewController3
I want to navigate back from
ViewController1 -> UIViewController.
Anyone know please solve this issues.
"Unwind" is your answer.
Create an IBAction method to unwind segue. Define this method in a controller in which you want to unwind (Controller from you want to jump back to main controller).
- (IBAction) prepareForUnwind:(UIStoryboardSegue *)segue {
}
Now connect back button (in this case "Home" button) with this method in Storyboard. To connect unwind action -> Ctrl-drag to "Exit" outlet button of your controller.
Note: If you are using Xcode version less than 6.0 than "Exit" outlet is located at bottom of your view controller.
This will navigate back to your root navigation controller. That is UIViewController.
For further separation you can give an identifier to unwind segue and make different actions for exit to last controller.
Select identifier from left list and give an identifier in Attributes inspector.
Key points:
Write unwind method in a controller which will be exited.
Connection to "Exit" delegate will only works after you define unwind method.
Ctrl+Drag from a control to the Exit symbol to select the unwind segue you want this control to perform
Unwind segues appear below the Exit symbol for each connection made
You can give those unwind segues an identifier to have different activities performed.
You can use
[navigationController popToViewController:<#(UIViewController *)#> animated:<#(BOOL)#>];
just provide the instance of the viewController you want to pop to and set animated property to YES if u want pop with animation and NO if not.
Here the controller UIViewController is the rootViewController of UINavigationController. So you just need to pop to the rootViewController from the ViewController1
[self.navigationController popToRootViewControllerAnimated:YES];
You can done by this:
ViewController *loginVC = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController"];
[self.navigationController popToViewController: loginVC animated:YES]

Making a segue through button action

I am trying to make a login in screen where when you press login it will check the username and password then if it is all good it will segue to the next view.
I have 1 view controller with 2 buttons just to test that I can successfully segue with a button action to another view controller. 1 button is my attempt to programmatically link the two view controllers and the other button is linked by a modal and it successfully switches between the views.
for the first button my code is,
#IBAction func testButton(sender: UIButton) {
performSegueWithIdentifier("nextView", sender: self)
}
for the storyboardID of the view controller to be switched to it is indeed 'nextView'
I get an error, 'NSInvalidArgumentException', reason: 'Receiver has no segue with identifier 'nextView'
I have cleaned up the code and also tried removing the app from the simulator.
Any suggestion on what the issue may be? Or is there a better way to make a login screen?
In order to perform segue on button tap with custom logic, select controller one (not button) control drag and drop on controller two. chose the segue and give an identifier value in storyboard. Then when you call performSegueWithIdentifier, it will work.
You need to set the identifier for the segue, not the StoryboardID of the view controller:
try this UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainstoryBoard" bundle:nil];
ViewController* viewController = [storyboard instantiateViewControllerWithIdentifier:#"StoryBoardIdentifier"];
[[self navigationController] pushViewController:viewController animated:YES];
performSegueWithIdentifier refers to the id of the segue not the storyboardID of the viewController you're trying to load. That being said, you could either create a segue between the view controller you're on to the destination view controller and use performSegueWithIdentifier, or you could create an instance of your storyboard and use its instantiateViewControllerWithIdentifier method which takes the storyboardID as a parameter. I'm posting from mobile so that might not be exact, but that should help you out.

Redirect to new view controller in the middle of navigation stack

I am fairly new to navigation view controllers and stacks in iOS. Please help me with this, tried searching for a long time couldn't find anything relevant.
I have a LoginViewController, a SWRevealViewController for side menu operation, a FirstViewController (the first one in navigation stack) and a SecondViewController (second in navigation stack).
I have to do the following in LoginViewController, assume login and found are two boolean variables:
if (login && !found) {
//redirect to FirstViewController : the following works
[self presentViewController:swReveal animated:NO completion:nil];
}
else if (login && found) {
//redirect to SecondViewController
}
Please help me fill the else if. Really appreciate your time!
So based on what I understood from your comments, FirstViewController is a subclass of TableViewController and SecondViewController is the DetailView.
So based on that, the best approach for "redirecting" to the DetailView (SecondViewController), would be creating a segue on the Storyboard, and then calling that segue programatically once the FirstViewController is loaded (in its viewDidLoad)
On both cases you would first show the FirstViewController and then depending on the if statement, you would either stay or go to the SecondViewController.
So first step: Create the segue from the Storyboard, and give it an identifier.
Second: Perform that segue programatically when the FirstViewController is loaded (and of course, the if statement is valid) by using:
[self performSegueWithIdentifier: #"MySegue" sender: self];
More on that subject:
Alternative ways to push view controllers with storyboard programmatically
Creating a segue programmatically

'Push segues can only be used when the source controller is managed by an instance of UINavigationController

I am having a problem with this.
In my root view controller I am having a textfield & one button. I am giving a condition like if i entered 0 in textfield then only it should move to next view.
upto here it is working correctly. But now here is problem. Here I am having one button & given navigation to third view controller for that button. here i am getting error as
Terminating app due to uncaught exception 'NSGenericException', reason: 'Push segues can only be used when the source controller is managed by an instance of UINavigationController.'
image ref: http://img12.imageshack.us/img12/8533/myp5.png
and i am giving action for button in first view as below
- (IBAction)Submit:(id)sender {
if([tf.text isEqual:#"0"])
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
SecondViewController *vc2 = [storyboard instantiateViewControllerWithIdentifier:#"SecondViewControllerID" ];
[self presentViewController:vc2 animated:YES completion:NULL];
}
}
Go To:
Editor--> Embed In --> Navigation Controller, to add Navigation Controller to your initial view
After looking at your screenshot, you either need to
Push your SecondViewController onto the existing navigation controller's stack instead of presenting it modally OR
You need to embed your SecondViewController in another navigation controller and then create and present that navigation controller modally from your SamplesViewController
Either way, SecondViewController needs to be embedded in a navigation controller before you can use Push Segues from it
Either embed your view controller in a Navigation controller or if there is a Navigation controller in the story board mak it the initial view controller
I also faced same problem. My problem was I was using model segue style (rather that push) for one before the current controller because of that I think it broke the Navigation chain before already.
Embed your view controller in a UINavigationController is a good option if there is no UINavigationController in the storyboard. Otherwise you can select the UINavigationController and select the root view controller in the inspector pane, then drag it to the UIViewController you want to use as root. the screenshot is as below:
I solved this by creating a custom UIStoryboardSegue between the UINavigationController and the destination view controller:
-(void) perform
{
assert([self.sourceViewController isKindOfClass:[MyNavigationController class]]);
MyNavigationController *launchController = (MyNavigationController *) self.sourceViewController;
[launchController setViewControllers:#[self.destinationViewController] animated:YES];
}
Try this. It works for me.when you set root view controller to first view and use self.presentViewController ,controller move to next view but instance of navigation controller is only for first view,third view required navigation instance so use self.navigationController instead of presentViewController.
NSString * storyboardName=#"Main";
UIStoryboard *storybord=[UIStoryboard storyboardWithName:storyboardName bundle:nil];
SecondViewController *vc=[storybord instantiateViewControllerWithIdentifier:#"SecondViewControllerID"];
[self.navigationController pushViewController:vc animated:YES];

How can I pass value between NavigationController and ViewController with StoryBoard?

I have a problem,
The following is my StoryBoard,
the first Controller is a TabBarController,
and it relation with A (ViewController).
A is a ViewController,
B is a NavigationController, A change page to B by modal segue
C is a ViewController, C will change to another page by push so I need a NavigationController
OK, I want to pass value from A to C,
now I can pass value from A to B by prepareForSegue,
However, because B and C have relationship but not segue,
So I can't pass value from B to C by prepareForSegue!!!
How can I pass value between NavigationController and ViewController with StoryBoard?
The Storyboard image is a little misleading here.
When you segue to B, actually you are segueing to the B/C combo as NavControllers always have at least one viewController in their stack (which is their topViewController and their [viewControllers objectAtIndex:0]).
So you do have a relationship directly from A to C.
How you access that controller depends on whether your segue is modal or push. In your case it is modal, but I will describe both so you can see the difference.
In either case, to pass data to C, you need to declare a property in it's header file
#interface CviewController: UIViewContrller
#property (assign) int dataFromA;
#end
push segue
In a push segue, it is actually C that is the destinationViewController, not B. In fact the push segue is governed by B, which is the UINavigationController for both A and C. The code behind the push segue is of the form
[self.navigationController pushViewController:otherViewController];
In AviewController's prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
CviewController* controller = segue.destinationViewController;
[controller setDataFromA:self.data];
}
It is possible in the storyboard to make a push segue line between two viewControllers that do not share a common UINavigationController. However when you run this you will get a crash error:
'Could not find a navigation controller for segue 'pushC'. Push segues can only be used when the source controller is managed by an instance of UINavigationController.'
Behind every good push segue lies a Navigation Controller.
modal segue
The code hiding behind a modal Segue is the UIViewController method
- (void)presentViewController:(UIViewController *)viewControllerToPresent
In a modal segue to a NavController/ViewController combo, the destination viewController is whatever the segue line points to. If it points to a viewController, that is the segue.destinationController (and the UINavigationController will be ignored, which is not what you want here); if it points to a UINavigationController, as in this case, that will be it's destinationController. But it is still straightforward to access the viewController, as it will be the navigation Controller's topViewController.
In AviewController's prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
CviewController* controller =
(CviewController*)[[segue destinationViewController] topViewController];
[controller setDataFromA:self.data];
}
Note that in this case we have to use old-style [[message passing] syntax]. If we use modern.property.syntax we get a compile error. That's because the program does not know the type of desinationViewController, and refuses to accept topViewController as a property of an unknown type. But it is happy to [send [real messages]] to an unknown type. We also have to (typecast*) to avoid compiler warnings.

Resources