Warning: attempt to present VC - ios

I am getting this warning, and I am not sure why. I tried getting rid of it by adding the subview but that didn't solve my problem either. Help please
Warning: Attempt to present on whose view is not in the window hierarchy!
Here is the code I am using on one VC:
[self dismissViewControllerAnimated:YES completion:^{
[self presentViewController:rootViewContoller animated:YES completion:nil];
}];
Edit: my app still works properly in regards to presenting view controllers I just want to know why the compiler is generating this warning

The warning shows up because you are presenting a new view controller (rootViewController) an another view controller that you actually just dismissed!
[self presentViewController:rootViewContoller animated:YES completion:nil]; is in the completion handler block of the dismissal of the other view controller, that means it gets called after that view controller has been dismissed.

You can use this:
[self dismissViewControllerAnimated:YES completion:^{
[self.presentingViewController presentViewController:rootViewContoller animated:YES completion:nil];
}];

Related

Dismiss and Present same view controller

i have a view controller and i need to dismiss it and present it back in same time.
i had tried dismiss it and call back the view controller but not working.
[self dismissViewControllerAnimated:YES completion:nil];
UIStoryboard *storyboard=[UIStoryboard storyboardWithName:#"Main" bundle:nil];
ExpandViewController *expandView=
[storyboard instantiateViewControllerWithIdentifier:#"ExpandViewController"];
expandView.delegate=self;
[expandView setEventDict:dict];
[self presentViewController:expandView animated:YES completion:NULL];
I am not exactly sure what outcome/functionality you are looking for in your question, but #matt is correct. However, you may be looking to have this happen seamlessly. Therefore you could use child view controllers instead of presenting the view controller using the [self presentViewController:VC animated:animate completion:nil] method.
Adding child vc:
[self addChildViewController:myVC];
[self.view addSubview:myVC.view];
[myVC didMoveToParentViewController:self];
Removing child vc:
[myVC willMoveToParentViewController:nil];
... remove subview.
You can set up a delegate between the two controllers to tell the parent when to dismiss the view to make things easy. You can also add the subviews at different indexes using [self.view insertSubview:myVC atIndex:index] or the other possible functions such as the insert above subview etc, to have one subview be added before dismissing the other to give a more seamless transition.
Hope this helps!
You can't present a view controller until the currently presented view controller has finished being dismissed. You won't know this has happened until the completion handler from your dismissal is called. Your mistake is that the completion handler is nil. Instead, provide a completion handler (in your first line), consisting of the remaining lines of your code. Thus, they will execute after the dismissal finishes.
[self dismissViewControllerAnimated:YES completion:^{
// ... the rest of your code goes in here ...
}];

dismiss viewController by using presentingViewController

I have three ViewControllers and its order is (A present B which presents C),
when I stay in the C viewController ,I have to dismiss ViewController to B viewController.
for C viewController ,its presentingViewCOntroller is B viewController
of course ,I can use
[self dismissViewControllerAnimated:YES completion:NULL];//self means C ViewController
But I was wondering I can also use the following method:
[self.presentingViewController dismissViewControllerAnimated:YES completion:NULL];
because the presentingViewController of C is B ViewController, but it did the same effect.
self means C ViewController while self.presentingViewController means B ViewController,but they also did the same work
The second question is I cannot use the following to dismiss two viewController in succession:
[self dismissViewControllerAnimated:YES completion:^{
[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:NULL];
}]; //self means C viewController
Thanks for your help!
of course ,I can use
[self dismissViewControllerAnimated:YES completion:NULL];//self means C ViewController
This only dismisses C, not B as you seem to want.
But I was wondering I can also use the following method:
[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:NULL];
Yes, this works. When in doubt, try it out.
The second question is I cannot use the following to dismiss two viewController in succession:
[self dismissViewControllerAnimated:YES completion:^{
[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:NULL];
}]; //self means C viewController
That's not a question. Anyway, the reason it doesn't work is that after you dismiss yourself, your presentingViewController is nil. You need to store it in a temporary variable.
UIViewController *gp = self.presentingViewController.presentingViewController;
[self dismissViewControllerAnimated:YES completion:^{
[gp dismissViewControllerAnimated:YES completion:nil];
[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}];
Of course, the two will have different animations, you'll need to decide which you prefer.
see documentation:
The presenting view controller is responsible for dismissing the view
controller it presented. If you call this method on the presented view
controller itself, it automatically forwards the message to the
presenting view controller.
Please check: self.presentingViewController.presentingViewController is A viewController or not.
if not, I think you need use delegate or handler.
In my case, I used a tabbarcontroller as a rootViewController. When I used self.presentingViewController.presentingViewController, I got rootViewController (tabbarcontroller) which it have no response to presentingViewControler method.

dismissViewControllerAnimated:completion: not executed

When I call dismissViewControllerAnimated:completion: to dismiss a UIViewController the completion block is never executed when the corresponding view is in the middle of being animated onto the screen (using presentViewController:animated:completion:).
The UIViewController does not even dissappear. It is like dismissViewControllerAnimated:completion: is being ignored.
The following code is a simplified code example because the original is much bigger. The code I have given below simulates a use-case where a network communication error might trigger a view to popup whilst another view is also being popped-up at the same time..
Code example:
NSLog(#"Presenting view");
[self presentViewController:changeLocationViewController animated:YES completion:^{
NSLog(#"View done presenting");
}];
NSLog(#"Dismissing view");
[self dismissViewControllerAnimated:NO completion:^{
NSLog(#"View done dismissing");
}];
Log output is:
2013-08-28 16:14:12.162 [1708:c07] Presenting view
2013-08-28 16:14:12.178 [1708:c07] Dismissing view
2013-08-28 16:14:12.583 [1708:c07] View done presenting
Does anyone know how to dismiss the UIViewController in these circumstances?
Thanks in advance.
The reason this code snippet isn't working is because the completion block in these methods are executed at a later time after the animations have completed. You can see this in your logs: "Dismissing view" happens before "View done presenting". Try this instead:
NSLog(#"Presenting view");
[self presentViewController:changeLocationViewController animated:YES completion:^{
NSLog(#"View done presenting");
NSLog(#"Dismissing view");
[self dismissViewControllerAnimated:NO completion:^{
NSLog(#"View done dismissing");
}];
}];
EDIT:
If you need to make sure the view is dismissed when the network error happens, try setting a boolean instance variable called networkErrorFound.
When you finish the network connection, set this to YES if an error happens. Then use this code:
[self presentViewController:changeLocationViewController animated:YES completion:^{
NSLog(#"View done presenting");
NSLog(#"Dismissing view");
if (self.networkErrorFound) {
[self dismissViewControllerAnimated:NO completion:^{
NSLog(#"View done dismissing");
}];
}
}];
That way, it'll wait until it's done presenting to dismiss. You would also need to handle the case that the error happens after the animation is done (for instance, a slow connection that eventually fails), but that's outside the scope of this question.
Why dont you dismiss it when its done loading?
[self presentViewController:changeLocationViewController animated:YES completion:^{
NSLog(#"View done presenting");
NSLog(#"Dismissing view");
[self dismissViewControllerAnimated:NO completion:^{
NSLog(#"View done dismissing");
}];
}];
OK. It seems like you want to present a VC, but if there is no network found, close the VC. The only reason that I can think of needing to do it this way is if the network only gets checked in the new VC that you are presenting (and want to dismiss if it fails to connect).
And you would be able to achieve that by implementing the code shown in the answer given by #aopsfan.
But think about that UI flow. You are telling a starving man (the user) he can have a sandwich (the next VC that he wants to see)... But WAIT! (dismiss the wanted VC) No, you can't have the sandwich (no network)! Fooled you!.
The way to do it to keep the UI flow nice and not aggravating, would be to check for network connection before presenting the VC. Probably check for network in the IBAction (?) that you use to present the new VC. That way, you can check before presenting. Instead of present-cancel
Heck, you could even show an HUD "in progress" View to let the user know what happening!

dismissViewControllerAnimated: not animating

I'm working with SVWebViewController. When I present the view controller here
SVModalWebViewController *webViewController = [[SVModalWebViewController alloc] initWithAddress:address];
webViewController.webDelegate = self;
[self presentViewController:webViewController animated:YES completion:nil];
The view controller slides up from the bottom, as expected. However, when the view controller is dismissed, calling
[self dismissViewControllerAnimated:YES completion:nil];
The view controller simply disappears. No slide animation down. Any thoughts?
EDIT
It turns out a lot of presentation animations aren't displaying correctly in the application. Some pushes on the navigation controller aren't sliding in or sliding out (but some are). They just appear.
[self dismissViewControllerAnimated:YES completion:NULL];
This should be in SVModalWebViewController not SVWebViewController
EDIT: Instead of modally segueing to the SVWebViewController you should push:
SVWebViewController *webViewController = [[SVWebViewController alloc] initWithAddress:#"http://google.com"];
[self.navigationController pushViewController:webViewController animated:YES];
And instead of dismissing you should:
[self.navigationController popViewControllerAnimated:YES];
From SVWebViewController viewWillAppear::
SVWebViewController needs to be contained in a
UINavigationController. If you are presenting SVWebViewController
modally, use SVModalWebViewController instead.
Is your main view controller contained in a navigation controller? If not, this could possibly cause the other animation issues you're facing.
The dismissal should be from the displayed modalViewController.
It happens to me when the destination view controller loads a big picture or background

Dismissing 2 ViewController consecutively

I try 2 ways to dismissed 2 viewcontrollers consecutively but only one of them got dismissed not the second one
method1
-(void) LoginDone:(NSNotification *)notif
{
[self dismissViewControllerAnimated:YES completion:NULL]; //previous viewcontroller
[self dismissViewControllerAnimated:YES completion:NULL]; //current viewcontroller
}
method2
-(void) LoginDone:(NSNotification *)notif
{
[self dismissViewControllerAnimated:YES completion:NULL];
[[NSNotificationCenter defaultCenter] postNotificationName:#"LoginDone2" object:nil];
}
-(void) LoginDone2:(NSNotification *)notif
{
[self dismissViewControllerAnimated:YES completion:NULL];
}
I need to find out a way to dismiss both the previous viewcontroller and current viewcontroller consecutively.
This is now an old question, but it seems to be exactly the problem I am having presently.
Here what I did:
[self.presentingViewController.presentingViewController
dismissViewControllerAnimated:YES completion:nil];
And it works for me. I hope it can be useful to someone.
By calling
[self dismissViewControllerAnimated:YES completion:NULL];
you are telling self to dismiss the view it presented. Telling twice the same self object to dismiss the view it presented, will not change the result. In other words self cannot represent the "current view" and the "previous view" at the same time as per your comment to the code. self is just a single controller representing a single view, either the current or the previous one.
To fix this, you should send the dismissViewControllerAnimated to self (that presented the top-most view, I assume) and to the other view controller object that presented the previous view.
In other words, I would expect something like this:
-(void) LoginDone:(NSNotification *)notif
{
[self dismissViewControllerAnimated:YES completion:NULL];
[self.previousController dismissViewControllerAnimated:YES completion:NULL];
}
Actually, you could send just one message to the second view controller and both views would be dismissed (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.
I know this is an old question but maybe somebody will look for solution on this issue so here it is:
-(void) closeModalViews
{
[previousVC dismissViewControllerAnimated:YES completion:^(void) {
[self dismissViewControllerAnimated:YES];
}];
}
I like JPetric's idea, but first you must dismiss the current view controller's view and only then can you dismiss the presenting view controller's view.
[self dismissViewControllerAnimated:NO completion:^(void) {
[self.presentingViewController dismissViewControllerAnimated:NO completion:nil];
}];
As far as I could understand you are trying something like below:
There are 2 view controllers.
You want both of them to be vanished.
Another controller comes in.
But the fact is only one controller is displayed, why you would need to dismiss 2 then?
You can use self.view.hidden=true; on the jumped viewcontrollers while animating back to the first viewcontroller. Using [self.presentingViewController dismiss...] is not working for me without hiding.

Resources