UINavigationController stack issues with push and pop - iphone

So I have four view controllers, A, B, C, D and they are shown in that order. Let's say that I am at view C and I want to go to view D, so I push view controller D into the navigation controller stack, however, what I want is that when D tries to go back it goes directly to view controller B instead of C.
Is there a particular way to achieve this? The logical way is to do popViewController and then pushViewController: C. I tried this and it didn't work out.

Instead of pushing D, call -setViewControllers:animated: on your navigation controller with an array of view controllers ordered A, B, and D.

So the order is A->B->C->D right? And from D, when the "Back" button is tapped you want to go to B?
That means popping D and then popping C so you get back to B. That's what popToViewController:animated: does.
UINavigationController Class Reference
popToViewController:animated:
Pops view controllers until the specified view controller is at the
top of the navigation stack.
Note that this is different from popToRootViewControllerAnimated:

You can use popToRootViewControllerAnimated: if A is at the bottom of the stack or popToViewControllerAnimated: if it's somewhere in the middle.

Related

Push from one view controller to another

I have a tricky situation. The following is the hierarchy of the views that I have.
(Root)Navigation-VC-->View A-->(via Segue push)--> View B-->View C
(Root)Navigation-VC-->View A-->(via modal push)-->(Nav Controller) View D-->View E
There is a cancel button in view D. When I click on it, it correctly shows view A. But For some reasons I would want it to go to View B in the first navigation hierarchy. How can I do such transitions?
If I create a modal segue from view D to view B it destroys the navigation hierarchy that view B is part of. If I push view B from view D then view B becomes a part of a different hierarchy altogether.
Can it be done? Do I have to rethink the design?
Well, after you dismiss the modal view controller, you can always call the method performSegueWithIdentifier:sender: to push view B. Just remember to set the segue identifier in your storyboard.
Call the method dismissViewControllerAnimated:completion: in view A and call the perform segue at the completion block. This is just to avoid any corruption that might happen to the navigation controller if you dismiss and perform segue at the same time.

Dismissing 3 layers of modal view

In my application, I have three layers of modal view controllers.
1) So my rootViewController is a tabbar.
2) On applicationDidFinishLaunching I am presenting a viewController, say viewController A modally above tabbar.
3) On click of a button in 'viewController A', I present another viewController B modally.
4) And a button action on viewController B presents navigationController modally with its rootViewController as viewController C.
5) Finally from viewController C, I want to go back to viewController A.
I tried using
[[[self parentViewController] parentViewController]dismissModalViewControllerAnimated:YES];
in viewController C, but it reverts me back to viewController B instead of viewController A.
How can I revert back to viewController A.
Any help would be appreciated.
push all the 'modal' views on a navigationControl with a transitionStyle that looks like the modalTransitionStyle..dont reinvent stuff
present all in one modal navigationController Id say :)
You've got a complex VC stack. You could as one poster suggested implement a custom dismissView method, but that would be fragile: if you reuse this view, or move it in your app, it will cease functioning, because it relies too much on specific knowledge of how other VCs have configured their state.
You could configure a delegation chain. This would be the standard way to manipulate views: the presenting VC is also responsible for removing anything it presents.
To do so, build a protocol implemented by B, and initialize C with a reference to B. Similarly, initialize B with a reference to A (with potentially the same protocol, depending on any other communication that needs to be passed between them.)
Then when the button is clicked on C, it calls B's delegate method. B unwinds C as appropriate, and calls A's delegate method. A unwinds B as appropriate.
This has the advantage of keeping VC knowledge encapsulated: A knows how it presented B, so it knows how to unpresent it, and B knows how it presented C, and knows how to un-present it. In no case does one VC need to make assumptions about how it was presented by another.
Implement the view dismissing method like:
- (IBAction)dismissView
{
[self dismissModalViewControllerAnimated:NO]; // dismiss c
[[self parentViewController] dismissModalViewControllerAnimated:NO]; //dismiss b
}
[self parentViewController] will return the parent view of viewControllerC, that's viewControllerB. So it'll dismiss that view too.

iphone app-Adding a view by removing previous view

i am using two view says A and B. I need to go to view B on pressing a button in View A so in the button action listener defined in view A, i wrote
-(IBAction)bt:(id)sender
{
B *mB=[[B alloc]initWithNib:#"B" bundle:nil];
[self.view addSubView:mB.view];
}
so that means view B has been added over view A. Thus, both the views remain on stack which consume memory i think.
Is their any way by which pressing the button in view A, it is removed and then view B is added??
you can use removeFromSuperview to remove view A
[view_A_Object removeFromSuperview];

dismissModalViewController issue in iOs

I have three view controllers, say A, B and C. I am navigating through this views like follows;
A -presenting-> B -presenting-> C -presenting-> B
And from B, if I dismiss I want to navigate to C. But instead of that, now it is moving to A. I can't use dismiss for navigation from C to B (some internal issues). So how can I fix this? Please help.
You hit into a limitation of dismissModalViewController: it will remove all of your modal views (source):
If you present several view controllers in succession, and thus build a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack. The top-most view is dismissed using its modal transition style, which may differ from the styles used by other view controllers lower in the stack.
What you could do is using a UINavigationController and simply push/pop controllers on to it according to your requirements.
Alternatively, you could simply display the views managed by the various controllers you have by directly calling addSubview on your top view and making sure they cover the whole screen and that the managing controller is correctly retained/released (the view is automatically when you add/remove it to another view).
As a hint, you could do it like this:
where you have presentModal..., use addSubview;
where you have dismiss..., use removeFromSuperview;
store a reference to any view controller whose view you manage like I suggest here in retain/strong property.
Hi use the below code in "C" viewcontroller
[[[self presentingViewController] presentingViewController] dismissModalViewControllerAnimated:YES];

How to identify the class of a Modal View controller?

In my application, I have to present two modal view controllers one above the other.
Lets say Modal View Controller B is placed over Modal View Controller A. Sometimes, there will be only A and no B.
I want to check from A that whether the top Modal View Controller is B. I know there is a method NSStringFromClass() but I can apply that only if I get the top Modal View Controller.
use (BOOL)[[youObjectInstance isKindOfClass:[ControllerClassYouWantToCheckAgainst class]]
Documentation here:
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html#//apple_ref/occ/intfm/NSObject/isKindOfClass: