I have a 1st VC (view controller) that should be modal, and it has a child modal VC that sometimes should be presented as soon as 1st VC will appear, but sometimes not.
So from a root VC I want to present 1st VC, and over the 1st VC present the child modal VC. But the user should only see the child VC modal transition (not the 1st VC).
AFAIK the 1st VC can only present a modal VC after viewDidAppear:, so I don't know how to make this possible, since when viewDidAppear: is called, the 1st VC is already visible to the user.
Don't want the user to see 2 modal transitions one after the other, but just the last modal transition, the child's one.
Any hint?
I figured out the simplest solution to this if you still haven't found a suitable one. You can use a UINavigationController to hold the 2 nested view controllers you are trying to display modally.
In the function that is meant to display the modal views you could do something like:
- (IBAction)showView3
{
ViewController2 *new2 = [[ViewController2 alloc] init];
ViewController3 *new3 = [[ViewController3 alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:new2];
nav.navigationBarHidden = YES;
[nav pushViewController:new3 animated:NO];
[self presentModalViewController:nav animated:YES];
}
Then function in ViewController3 to dismiss it would have:
[self.navigationController popViewControllerAnimated:YES];
And the one in ViewController2 would have:
[self dismissModalViewControllerAnimated:YES];
The only issue I can see with this is aesthetics, as by default the transition from view3 to view2 is a horizontal animation but the one from view2 back to view1 is vertical. You could of course change that as well to make them all horizontal, or all vertical, or however you want.
You could have 1 modal view controller with 2 views. Then just pick which view you want to display when the view controller loads.
You should be able to put presentModalViewController anywhere you want, including viewWillAppear.
[self presentModalViewController:myModalViewController animated:NO];
edit: for anyone reading this, see my other (correct) answer, because this one isn't.
Related
I am opening second view controller on button click from fist viewController,but its animating from bottom.I want to open it in right to left.
You may be presenting the second view controller on first view button tap.
The view transition from right to left will work when you do pushing a second view.
For enable pushing the second view, at first your first view should be inside navigation controller.
If your first view is already inside a navigation controller then do the following for pushing second view:
Case 1: If your are using storyboard and First view is already embedded in Navigation controller
set storyboardID for the second view controller in storyboard (Eg. here storyboardID is same as the class name)
Do this code on your button tap of first view:
SecondViewController *secondViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
[self.navigationController pushViewController:secondViewController animates:YES];
Case 2: If you are using storyboard but First view controller is not embedded in Navigation Controller:
1. Embed the First view in Navigarion controller
1.1. Open storyboard file and select the First View Controller
1.2. Goto Editor->Embed In-> Navigation Controller.
Then do the step Case:1's 2nd step.
Case 3: If you are using XIB files and first view is not in navigation controller.
1. For loading first view in AppDelegate.m application:didFnishLoading: method do as follows:
FirstViewController *firstViewController = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:firstViewController];
self.window.rootViewController = navigationController;
Then for pushing second view on first view button do as follows:
SecondViewController *secondViewController = [[FirstViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[self.navigationController pushViewController:secondViewController animates:YES];
If this is not helpful, then just post what you did exactly then exact solution can be given. Because what approach you are using to load view is not mentioned in your question.
Use
[self pushViewController:yourViewController animated:YES];
instead of
[self presentViewController:yourViewController animated:YES completion:nil];
The first piece of code pushes the second view controller in the screen from right to left.
The second line of code, which is what you have probably written in your app presents the view controller modally, meaning from bottom to top.
How can i go back 2 or 3 views back without using navigation controller? That is in my app, there is a main menu view. i want to reach that menu from all the other pages (from multiple views). How can this be implemented? with
[self dismissModalViewControllerAnimated:YES]; this cannot be implemented i suppose.
Anybody please help me..
I found the solution.
Of course you can find the solution in the most obvious place so reading from the UIViewController reference for the dismissModalViewControllerAnimated method ...
If you present several modal view controllers in succession, and thus build a stack of modal 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.
so it's enough to call the dismissModalViewControllerAnimated on the target View. I used the following code:
[[[[[self parentViewController] parentViewController] parentViewController] parentViewController] dismissModalViewControllerAnimated:YES];
to go back to my home.
Copied from here
"Going 2 views back without navigation controller"
Hmmm, I'm not sure if this misses the point, but the easiest way to do this is to use the popToRootViewControllerAnimated in the Navigation Controller:
[self.navigationController popToRootViewControllerAnimated:TRUE];
So, supposing you had a series of three screens in a Navigation Controller, and on the third screen you wanted the "Back" button to take you back to the initial screen.
On the third screen, you would add this code:
-(void)viewDidLoad
{
[super viewDidLoad];
// change the back button and add an event handler
self.navigationItem.leftBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:#"Back"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(handleBack:)];
}
-(void)handleBack:(id)sender
{
NSLog(#"About to go back to the first screen..");
[self.navigationController popToRootViewControllerAnimated:TRUE];
}
Do you want to go "two or three VIEWS back"? Use removeFromSuperview? Or are you talking about ViewControllers?
Are you using Storyboard?
If yes do:
- (void)showModalAssistantViewController
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"AssistantStoryboard" bundle:nil];
AssistantRootViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:#"AssistantNavigationController"];
[viewController setModalPresentationStyle:UIModalPresentationFullScreen];
[viewController setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[self.navigationController presentModalViewController:viewController animated:YES];
//... or pushToViewController ... whatever, you get the point.
}
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
So I have a tabBarController as a modalview, and it shows up fine. As I click some of the tabs, the views are loading properly. I want to dismiss the modalView when I click on tabBarController.selectedIndex ==4
So I write in the viewDidLoad and also tried in the viewWillAppear of that view controller to dismissModalViewController and it does not work.
I tried
[self.parentViewController dismissModalViewControllerAnimated:YES];
// ... And also //
[self dismissModalViewControllerAnimated:YES];
Could someone point out why it does not work ?
All you have to do is pass a reference to the modally presented VC pointing on the VC that will present it modally.
Define a weak reference as a property in the UITabBarController subclass, and send a message to dismiss it when required.
For example using a property named mainViewController :
MySubclass *tbController = [[MySubclass ....];
tbController.mainViewController = self;
[self presentModalViewController:tbController animated:YES];
Then in MySubclass define
#property(assign) UIViewController *mainViewController;
and synthesize it, then when the tab you want gets selected :
[self.mainViewController dismissModalViewControllerAnimated:YES];
I think the 4th view controller (of the tab bar controller) is trying to get dismissed by the line
[self.parentViewController dismissModalViewControllerAnimated:YES];
Since this 4th view controller was not presented by any controller, this wont work.
And it is dismissing it's modal view controller by the line
[self dismissModalViewControllerAnimated:YES];
Since, this 4th view controller did not presented any view controller, this again should not work.
You want to dismiss the tab bar controller and not its 4th view controller.
Basically, you can get the reference of tab bar controller from the 4th view controller.
As, [yourFourthViewController.tabBarController.parentViewController dismissModalViewControllerAnimated:YES];
I am guessing this without actually trying. Let me know if this works.
If you have the UINavigationController as the parent controller then the following line will work for you.
[self dismissModalViewControllerAnimated:YES];
But here I think you have the UIViewController is the parent controller instead of the UINavigationController. So, You can do one thing when presentModalViewController.
if(objView == nil)
objView = [[YourViewController alloc] initWithNibName:#"YourViewController" bundle:nil];
UINavigationController *navigationController1 = [[UINavigationController alloc] initWithRootViewController:objView];
[self presentModalViewController:navigationController1 animated:YES];
Let me know if you need more help or any questions.
How would I go about chaining several modal controllers from a UITabBarController's view? The View Programming Guide from Apple says this is feasible but when I attempt such a task, I get the error,
"*Assertion failure in -[UIWindowController transition:fromViewController:toViewController:target:didEndSelector:], /SourceCache/UIKit_Sim/UIKit-1447.6.4/UIWindowController.m:186
The Class hierarchy is something like this:
UITabBarController -> 1 child is a UIViewController inherited class named, Tab1Controller.
Tab1Controller -> orchestrates each of the 2 controllers that need to be presented modally.
Launches 1 modal UIViewController and when this finishes up (get called via a callback), dismisses it and then initiates another modal UIViewController.
It's as if there's not enough time between the two modal controllers ending and starting.
Is there any sample code that shows how to have one modal controller after another can be chained?
See my answer to this SO question:
Correct way of showing consecutive modalViews
It's as if there's not enough time between the two modal controllers ending and starting.
I think you've hit the nail on the head there. You cannot present a new modal view controller until the previous one has finished disappearing and the viewDidAppear: method is called on the view controller that had been being covered by the old modal view.
Another option would be to present the second modal view on top of the first, e.g.
[firstModalViewController presentModalViewController:secondModalViewController animated:YES]
You can then call [firstModalViewController dismissModalViewControllerAnimated:YES] to dismiss the second (returning to the first), or [self dismissModalViewControllerAnimated:YES] to dismiss both at once.
// present modal view inside another presented modal view
FirstViewController *firstVC = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController: firstVC];
// Note: you can use your viewcontroller instead self.window.rootViewController
[self.window.rootViewController presentViewController:navController animated:YES completion:^{
//code...
SecondViewController *secondVC = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[navController presentViewController: secondVC animated:YES completion:nil];
}
}];
I've read the post : Pop-up modal with UITableView on iPhone
and I don't understand the following part of the answer (as I can't comment the original post, I create this new question) :
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:optionViewController];
Why allocate a new controller as the window from where the new optionController is called may already have one ?
What if I just write :
OptionViewController* optionViewController = [[OptionViewController alloc] initWithNibName:#"OptionView" bundle:nil];
[self.navigationController presentModalViewController:optionViewController animated:YES];
It seems to work...
If I have a list, that goes to a detail View, from where I switch to a modify view, and then from where I call this option window, what would be the code to use to call this optionWindow ? This one ? Any other one ? I really have a problem dealing with UINavigationController between screens... (where should be defined the first one, what should be passed between screens, when may I create a new one, ...)
Modal views don't use the UINavigationController of their parent. This means that if you need a "stack" of new view controllers in your modal view then you'll need to add your own. On the other hand, if you don't need the functionality of a navigation controller in your modal view then there's no reason to add one.
Here are sone more details of how I did it in two of my apps:
My root view controller has a UINavigationController. I open a modal view using this code:
TwitterPostViewController* vc = [[TwitterPostViewController alloc] init];
[viewc presentModalViewController:vc animated:YES];
[vc release];
The modal view is then dismissed using this code:
[self dismissModalViewControllerAnimated:YES];