Creating modal view from another modal view fails - ios

In a view that was created modally, pressing a button causes the modal view to be dismissed and another modal view to load.
- (void)loadLanguageSelectionView {
[self dismissViewControllerAnimated:YES completion:nil];
UIViewController *languageSelectionController = [[LanguageSelectionViewController alloc] initWithNibName:nil bundle:nil];
[languageSelectionController setModalPresentationStyle:UIModalPresentationCustom];
[languageSelectionController setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[self presentViewController:languageSelectionController animated:YES completion:nil];
}
The following error is thrown when this code block executes:
DenkoStation[4259:73173] Warning: Attempt to present <LanguageSelectionViewController: 0x7b185430> on <ViewController: 0x79f52e50> whose view is not in the window hierarchy!
What surprises me is the fact that the code was running happily before I made some changes to my code as outlined here.
Where's the mistake?

Because you are trying to present a viewController on top of a viewController which is already dismissed and no longer in window hierarchy.
What you can try is, you can take the ParentViewController reference from current viewController and then you can present new viewController on ParentViewController Like This :
- (void)loadLanguageSelectionView {
UIViewController *parentController = self.presentingViewController;
[self dismissViewControllerAnimated:YES completion:^{
UIViewController *languageSelectionController = [[LanguageSelectionViewController alloc] initWithNibName:nil bundle:nil];
[languageSelectionController setModalPresentationStyle:UIModalPresentationCustom];
[languageSelectionController setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[parentController presentViewController:languageSelectionController animated:YES completion:nil];
}];
}

Related

Modally present view controller after dismissing view controller

This issue only occurs on iPhone 5, regardless of iOS version.
I present the secondViewController from the firstViewController it
is presented this time.
I then dismiss the secondViewController.
I attempt to present the secondViewController again from the
firstViewController, this time it isn't presented but the UI is blocked,
From logging the process I can see that viewWillAppear method is called the first time but not the second time.
FirstViewController
- (void)presentView {
SecondViewController *secondViewController = [[SecondViewController alloc] init];
secondViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:secondViewController animated:YES completion:nil];
}
SecondViewController
- (void)dismissView {
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}

when i use dismissviewcontrolleranimated , i got exc_bad_access

I got an error exc_bad_access,when i use dismissviewcontrolleranimated
the presentViewController code is:
TestViewController *testViewController=[[TestViewController alloc] init];
UINavigationController *nav=[[UINavigationController alloc] initWithRootViewController:testViewController];
[self presentViewController:nav animated:YES completion:^{
NSLog(#"presentViewController is finish");
}];
but,when i remove UINavigationController ,is error is disappear.
like this:
TestViewController *testViewController=[[TestViewController alloc] init];
[self presentViewController:testViewController animated:YES completion:^{
NSLog(#"presentViewController is finish");
}];
Thanks for help.
Present View Controller is presented over a "Root View Controller" not a UINavigationController.
You should present your VC from the Parent VC or Base VC like this
TestViewController *testViewController=[self.storyboard instantiateViewControllerWithIdentifier:#"storyboardIDofViewController"];//set the storyboard ID of the TestViewController in your storyboard by selecting attribute inspector after selecting the view controller.
[self presentViewController:testViewController animated:YES completion:^{
NSLog(#"presentViewController is finish");
}];
This is the correct way to present a VC from another VC.
UINavigationController have Push and Pull transitions and you are trying to apply Modal Transition to it.

How to move from one view controller to another with an Action?

IM not Using Storyboard.
Ive place a button, on my PlayViewController and when tapped I want the user to go back to the Main menu which is the ViewController.
When I add this line of code:
- (IBAction)backToMenu:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
It dismisses the ViewController - I want it to present it, So I used:
ViewController *viewcontroller = [[ViewController alloc]initWithNibName:#"ViewController" bundle:nil];
viewcontroller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:viewcontroller animated:YES completion:nil];
I get this ERROR: "Receiver 'ViewController' for class is a forward declaration"
I need to present my main menu, how am i supposed to do it?
You need to import the target view controller in your PlayViewController:
#import "ViewController.h"

Muiltple Modal UIViewControllers | Dismiss Top Modal UIViewController Only

My UIViewController stack looks as follows:
+------ UIViewController_C (presented)
+---- UIViewController_B (presented)
+-- UIViewController_A (pushed)
When I call -dismissViewController:animated on UIViewController_C, UINavigationController dismisses both UIViewController_C and UIViewController_B together, as per the docs with animation on _C, and none on _B.
What is the most compliant way to dismiss _C only?
try as below
after pushing to UIViewController_A present UIViewController_B as below code.
UIViewController_B *bbp=[[UIViewController_B alloc]initWithNibName:#"UIViewController_B" bundle:nil];
UINavigationController *passcodeNavigationController = [[UINavigationController alloc] initWithRootViewController:bbp];
passcodeNavigationController.navigationBar.hidden=YES;
[self.navigationController presentModalViewController:passcodeNavigationController animated:YES];
[passcodeNavigationController release];
now from UIViewController_B try to present in UIViewController_C as below code.
UIViewController_C *bbp=[[UIViewController_C alloc]initWithNibName:#"UIViewController_C" bundle:nil];
UINavigationController *passcodeNavigationController = [[UINavigationController alloc] initWithRootViewController:bbp];
passcodeNavigationController.navigationBar.hidden=YES;
[self.navigationController presentModalViewController:passcodeNavigationController animated:YES];
[passcodeNavigationController release];
last and final thing on every back button of view controller write below line of code.
[self dismissModalViewControllerAnimated:YES];
if you want more help than comment bellow.
One Solution:
UIViewControllers presented modally are not necessarily deallocated on -dismissViewController:animated.
This means that by passing a reference to UIViewController_A through _B to _C, you can call -presentViewController:animated and -dismissViewController:animated for the respective UIViewControllers via UIViewController_A.
Code:
1. UIViewController_B
- (void) showUIViewController_C {
[self dismissViewControllerAnimated:TRUE completion:^{
UIViewController_C *controller_C = [[UIViewController_C alloc] init];
controller_C.parentController = self;
[self.parentController controller_C animated:TRUE completion:nil];
}];
}
2. UIViewController_C
- (void) dismissUIViewController_C {
[self dismissViewControllerAnimated:TRUE completion:^{
[self.parentController.parentController presentViewController:self.parentController animated:TRUE completion:nil];
}];
}
Where I am using *parentController as the naming convention for whatever class your previous UIViewController on the stack may be.
It dips back to UIViewController_A briefly because I am calling -dismiss and -present in the completion block, though that actually looks rather fun.

Issue with definesPresentationContext / UIModalPresentationCurrentContext - Current context view controller gets lost

This only accours if you are presenting in a view controller that is managed by a navigation controller.
The reproduction steps are:
1 - Present a view controller using UIModalPresentationCurrentContext
self.definesPresentationContext = YES;
ViewController* viewController = [[ViewController alloc] init];
viewController.modalPresentationStyle = UIModalPresentationCurrentContext;
[presentOnViewController presentViewController:viewController animated:YES completion:nil];
2 - Present a view controller over the top using the default full screen presentation style
ViewController* viewController = [[ViewController alloc] init];
[self presentViewController:viewController animated:YES completion:nil];
3 - Dismiss the top presented view controller (the full screen one)
[self dismissViewControllerAnimated:YES completion:nil];
Now the problem is the 2nd view controller (presented using UIModalPresentationCurrentContext) disappears. Also it is impossible to present another view controller using UIModalPresentationCurrentContext, because the system thinks its still there.
I believe the issue is a bug in the framework. As mentioned it only occurs when the presenting in a view controller managed by a navigation controller. There is a nasty work around which uses the containment API. It creates a dummy view controller which views are presented from. The steps are:
1 - When presenting a view in context who's parent is a navigation controller, use a dummy view controller:
- (void)presentInContext
{
UIViewController* presentOnViewController = self;
if ([self.parentViewController isKindOfClass:[UINavigationController class]])
{
// Work around - Create an invisible view controller
presentOnViewController = [[DummyViewController alloc] init];
presentOnViewController.view.frame = self.view.frame;
// Containment API
[self addChildViewController:presentOnViewController];
[self.view addSubview:presentOnViewController.view];
[presentOnViewController didMoveToParentViewController:self];
presentOnViewController.definesPresentationContext = YES;
}
ViewController* viewController = [[ViewController alloc] init];
viewController.modalPresentationStyle = UIModalPresentationCurrentContext;
[presentOnViewController presentViewController:viewController animated:YES completion:nil];
}
2 - When dismissing the view controller tidy up
- (void)dismissSelf
{
__weak UIViewController* presentingViewController = self.presentingViewController;
[self dismissViewControllerAnimated:YES completion:^{
// Remove the dummy view controller
if ([presentingViewController isKindOfClass:[DummyViewController class]])
{
[presentingViewController willMoveToParentViewController:nil];
[presentingViewController.view removeFromSuperview];
[presentingViewController removeFromParentViewController];
}
}];
}
Thats it... The fix is dirty, but does the trick with no visual flicker.

Resources