How to push some viewcontrollers with segue at a time - ios

When the NavigationController has 3 view controllers (A,B,C).
I want to move to the view controller C from A via B with using a segue at a time.
In this case, what's the best practice?

I believe you need perform seque B->C manually once seque A->B is finished (for example in viewDidAppear).

Use this code:
UINavigationController *navController = [self navigationController];
[navController performSegueWithIdentifier:#"SegueIdentifier" sender:self];
I assume you have a segue with appropriate identifier.

I can not understand the logic to go A-C but moving the way A-B-C.
but this can be done perform seague A-B . in B use the method viewWillAppear() or viewDidload to perform the segue for C .
Hope this will solve your problem.

Related

iOS8: Pushing View Controller in prepareForSegue for another flashes it

I have 3 View Controllers, conveniently named A, B, C.
A is presented using a UINavigationController, and has a push segue to C.
My desired effect is that after performing the segue, C's back button will pop us into B, and then B's back button pop us to A. Effectively, this means that segueing to C will put both B and C onto the stack.
in iOS7, I've used the following (redacted) code successfully:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
CViewController *slotViewer = segue.destinationViewController;
/* Do Stuff */
BViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"B"];
[self.navigationController pushViewController:controller animated:NO];
}
The result appearance was a smooth transition from A to C, while B is loaded and B's ViewWillAppear is only called when clicking on C's back button.
However, on iOS8, this breaks: The transition briefly flashes B on the screen, its viewWillAppear is called, and only then C is shown.
Any idiomatic way to perform this transition in iOS8?
I know I can use the method described here but it feels awkward, and I'd rather use the Segues all the way.
The method (setViewControllers) you linked was designed to do exactly you want. Why is it awkward? It's provided by Apple.. Besides that there is no way to use segues only. Your previous solution was same like pushing first one programatically and right after second one by interface builder..this is awkward man:).
Please don't do this. You're not supposed modify the navigation stack like that! It's awkward.

How to unwind segue several steps back?

There are a lot of stuff on the net according the topic but I don't get it. I have an App with Custom segue implementation and without Navigation controller. There are cases in which I need to unwind back several steps.
For implementation I use simple calls:
CODE CUSTOM SEGUE
For wind:
[[self sourceViewController] presentModalViewController:[self destinationViewController] animated:YES];
For unwind:
[[self destinationViewController] dismissViewControllerAnimated: YES completion: nil];
As I understand when I wind segue somewhere in the memory there is data which is used during the unwind. For that reason in the custom unwind I only use read only property destinationViewController.
So how can I unwind several steps back in one action? Or I have to make several unwinds in different View controllers?
I read the following question, but I don't understand implementation.
Bellow I put example of my apps logic:
EXAMPLE
I have 4 VC which is in a chain:
VC A -> VC B -> VC C -> VC D
I wind and unwind back and forth. The logic is ok. There are situation in which I need to unwind back from VC D to VC B. How to do that? Can I unwind directly to VC B or I have to unwind to VC C and then in the unwind handler to unwind to VC B?
I also thought of additional segue from VC D to VC B, but there are remarks on the net that this is not the right way, because segue chain will get messy.
The answer to What are Unwind segues for and how do you use them? has everything you need to know about unwindSegues (I suggest you re-read it).
But for a more direct answer, yes you can unwind back from VC D to VC B. To do that you have to first implement the method in VC B:
- (IBAction)unwindToVCB:(UIStoryboardSegue *)unwindSegue
{
}
after doing so, go to the IB, and control-drag a button's action to the Exit icon, you should then pick the method you created above as the selector. (This is taken directly from the question/answer stated above).
Again, for a clearer version of what I said, read the answer of the linked question I mentioned above.
You have to use UINavigationController, just add it in storyboard as mainViewController and set 'A' ViewController as root view controller for it, then change all segues to push segue, set 'Identifires' for them, and you can use performSegueWithIdentifire to push view controller and inside view controller:
[self.navigationController popViewControllerAnimated:];
or
[self.navigationController popToViewController: animated:];
to dismiss it.

ECSlidingViewController with Push and Unwind Segue

I am using ECSlidingViewController with storyboards. ECSlidingVC is my root (starting) controller. My left menu is a TableView with static cells, and my TopViewController is a navigation controller. I want to have a single NavigationController for all my app.
From my left menu i cant use push or unwind segues, i understand that part though. i can only use ECSlidingSegue which changes topviewController of ECSlidingVC and which destroys my navigation controller and it's stack.
i want to be able to go back from a menu item VC to previous VC in my main nav controller. lets say basically i want ECSlidingVC to not change topViewController but push destination viewController to my source.topViewController.navigationController.
Also i need to use unwind segues with my menu items. i need to go back to a VC in my main nav controller.
i inspected ECSlidingSegue source code and all it does is to replace topViewController.
is there a built in method (or segue) in ECSlidingViewController for pushing (or unwinding) VC into source.topViewController.navController or do i need to implement a custom segue myself?
I think the best way to go is for you to implement a custom segue yourself. Something like ECSlidingNavigationSegue, which would look for your topViewController, then check whether it's a UINavigationController and then push the destinationController to it.
It's basically the same perform method as the ECSlidingSegue, but with this feature of pushing a controller to the topViewController instead of replacing it.
Good luck!
In case someone haven't found answer, I did it in this way.
1- #import "UIViewController+ECSlidingViewController.h" to your menuViewController
2- Set stroboardID of your destinationViewController to "someID"
3- When triggering some action, in backend, use this code:
if(self.slidingViewController.currentTopViewPosition == ECSlidingViewControllerTopViewPositionCentered){
[self.slidingViewController anchorTopViewToRightAnimated:YES];
}
else{
self.slidingViewController.topViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"someID"];
[self.slidingViewController resetTopViewAnimated:YES];
}

Cannot programmatically perform segue

I have a storyboard segue with an identifier that is 'Push to ResumeView'.
I try calling it in the ViewController that I'm in at the point, by doing
[self performSegueWithIdentifier: #"Push to ResumeView" sender: self];.
But nothing happens?
I'd much rather just push the ViewController using the top NavigationController or something, but I can't see how to do that either.
Try implementing the shouldPerformSegueWithIdentifier:sender: or prepareForSegue:sender: methods in the 'from' view controller. Put a break point or NSLog() inside the method to inspect the segue identifier. This will prove that you indeed set up the segue correctly in the storyboard.
If you want to manually push your next view controller to the top of the navigation controller, use pushViewController:animated:. However, if you are using storyboard, the preferred way is to use segues.
Try this one.
UIViewController *yourResumeView=[self.storyboard instantiateViewControllerWithIdentifier:#"PushToResumeView"];
[self.navigationController pushViewController:yourResumeView animated:YES];

Push UIViewController after popping to root view

I have an app using storyboards and a navigation controller. At some stage in my app flow I get about four views on the view stack at which point I must pop off all the views until I get to the root view. After which I need to manually push another view.
I've tried various things with no luck. I've tried to use the built-in API call:
[self.navigationController popToRootViewControllerAnimated:YES];
At which point I try to call a push segue by referencing the root view and calling the segue method.
RootView *obj = [[RootView alloc] init];
[obj callSegue];
Or
[self.navigationController performSegueWithIdentifier:#"pushView" sender:self];
At any rate, I'm completely stumped on this one. Can anyone help?
UPDATE:
Thanks for the replies everyone. I was digging around some more and found a solution, one of many I'm sure.
// Reference to navigation controller. Apparently if you use self.navigationController in a popToRootViewController call it sets self.navigationController to nil.
UINavigationController *navigationController = self.navigationController;
[navigationController popToRootViewControllerAnimated:NO];
// Reference to view to push - must set storyboard ID in inspector
ViewToPush *viewRef = (ViewToPush *)[self.storyboard instantiateViewControllerWithIdentifier:#"gameView"];
[navigationController pushViewController:gameView animated:NO];
How about this?
[self.navigationController setViewControllers:#[rootViewController, viewControllerTwo] animated:YES];
This sets your stack to your root and a new controller and push animations are used. If you need a quick'n dirty reference for rootViewController, you can use [[self.navigationController viewControllers] objectAtIndex:0].
A good solution to this is to use an "Unwind Segue". Basically, an unwind segue is a segue that takes you back down the stack of pushed controllers, and then performs an IBAction method in the destination controller. What you want to do is make an unwind segue from your current controller to the root, and then put a performSegueWithIdentifier: call in the called method.
Here's a tutorial on unwind segues: Tutorial
Meybe you can try this :
Set a flag (a #property) in your root VC, something like shouldPushAutomatically
In the VC where you call [self.navigationController popToRootViewControllerAnimated:YES];, implement the prepareForSegue:WithIdentifier: method. In this method, use (MyVC*)segue.destinationViewController to access your root VC and set yourflag to YES.
In the viewDidLoad of your root VC, try calling your push segue (in fact, you may need to call it in viewDidAppear).
Not sure if this will work, but that's the way I would try to make it work.

Resources