UIViewController not being presented due to another being recently dismissed - ios

I have one view controller MainViewController which (through buttons) allows the user to present/dismiss another InventoryViewController modally.
A third view controller CallViewcontroller is then presented programmatically from MainViewController at specific timed intervals. Before this happens, InventoryViewController is dismissed.
If InventoryViewController is never presented, CallViewController is presented without any problems.
If InventoryViewController is visible/present when CallViewController is launched, there also don't seem to be any issues.
But if InventoryViewController is presented then manually dismissed by the user, at any point, when CallViewController is presented the app partially freezes and the console throws an error -
Warning: Attempt to present <CallViewController: 0x17e31bb0> on <MainViewController: 0x18d3fc00> whose view is not in the window hierarchy!
Code to launch InventoryViewController from MainViewController:
[self performSegueWithIdentifier:#"segueToInventoryView" sender:self];
Code to dismiss InventoryViewController from a button from within MainViewController:
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
Code to dismiss InventoryViewController programmatically from MainViewController just before CallViewController is presented:
[self dismissViewControllerAnimated:NO completion:nil];
(I also use a timer to delay the method that presents CallViewController to make sure InventoryViewController has been properly dismissed)
I'm guessing that the error is saying that I can't present a modal from MainViewController because it isn't at the top of the stack, suggesting that InventoryViewController hasn't been properly dismissed.
Originally my code was written for iOS7, now the BaseSDK is iOS9 ( I am returning to this project and iOS programming generally after a year). As far as I am aware, this problem didn't occur before. So is this being caused by changes brought on by iOS8/9, or is there something else happening here?
Any help appreciated.

Found the solution, I had a flag in MainViewController for checking if InventoryViewController had been dismissed, which wasn't being set correctly. This was causing [self dismissViewControllerAnimated:NO completion:nil] to be called twice, and the second time round it was actually dismissing MainViewController, by sending the call to it's parent!
So the fact that [self dismissViewControllerAnimated:NO completion:nil] can be called on both the presenting and presented view controller is perhaps something to watch out for.
The code outlined above all seems to work fine in iOS8/9

Related

How do I display an alert over a PageViewController after a popover dismissal?

I have a a VC structure like this
UIPageViewController -> detailViewController -> popoverviewcontroller
The popoverviewcontroller is dismissed using an unwind segue, bringing us back to the detailviewcontroller
Now, after the popover is done being dismissed, I would like to refresh the pages on the pagecontroller, since the action the user takes has changed the data.
I would also like to display an alert notifying the user about whether they were successful.
So I tried putting this code in the pageViewcontroller
- (IBAction) unwindFromPopup:(UIStoryboardSegue*)unwindSegue{
[self refreshPages];
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:#"alert" message:#"this should appear" preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:alertController animated:YES completion:nil];
}
I tried moving the above code to the detail view controller instead, but I am getting no result from this. No error or anything, just a complete lack of alert. I put a breakpoint in the segue, and the code gets called. But no alert.
I thought of putting the code in one of the respective viewDidAppear methods, but for some reason viewDidAppear does not get called for either the pageviewcontroller or the detailview controller after I dismiss the popup.
So at this point I have no idea how to make this alert appear.
Do I need to post my full code, or is my problem apparent with the details I've included?
Thanks - based on your comment ... long ago in a distant version of iOS I performed all the possible segues and noted what gets called when and have a table of that that I based my answer on. I must admit, nowadays I get most done using the presentation controller delegate.
Anyhow, to reply to your question, when you pop or modally present a controller, the controller that is being presented will message beingPresented and beingDismissed when it is done and you might be able to use this for what you are trying to do.
When you push a controller it will message isMovingToParentViewController when shown and isMovingFromParentViewController when dismissed, again in the controller being presented.
Back to a pop ... it will message prepareForSegue in the presenting VC and viewWillAppear and viewDidAppear in the presented VC and, when dismissing, will message only viewWillDisappear and viewDidDisappear in the presented VC, thus your problem. At least it will also message beingDismissed as mentioned and if you can use that I am really glad for you.

Setting the rootViewController after a modal view has been presented

I have an app where I re-init the app if it's been in the background for too long. When the user opens up the app after the allotted time, the re-init happens, and I display the splash screen while I get the data I need. When I get the data from the server I set the window.rootViewController property to a new value. If the old root view controller has had a view controller presented modally, and that view controller was being displayed when the re-init happens, dealloc doesn't get called on the view controller (I've tested this by putting NSLog's in the dealloc method). In the case where a modal view controller was not presented, the dealloc gets called as expected.
Does anyone know of a solution to this? I'm not sure if it's an Apple bug, or if it's something that I need to handle on my own.
The solution that I came up with was before I set the RootViewController, I call
- (void)_dismissRootViewControllersModalViewsIfAny {
UIViewController *rootViewController = self.window.rootViewController;
if (rootViewController.presentedViewController || rootViewController.presentingViewController)
{
[rootViewController dismissViewControllerAnimated:NO completion:nil];
}
}
This is a method that I created, which makes sure that if there is a modal view controller to dismiss, it will be dismissed.
Your modal view is presented by the rootViewController (it's presentingViewController property is set to the rootViewController), that might be the source of your problem.
You can set your rootViewController to an instance of UINavigationController and then just use its setViewControllers:animated: method to display a freshly instantiated view controller instead of switching the window's rootViewController.

KVO When View Dismissed

I currently have a main web view (UIViewController) that presents a UIViewController like this:
[self presentViewController:controller animated:YES completion:nil];
I am trying to observe when the presented view controller gets dismissed using:
[self dismissViewControllerAnimated:YES completion:nil];
I have tried observing a variable in the main web view that the presented view sets when it's being dismissed, but that doesn't seem to work.
How would I go about observing when the presented view gets dismissed?
Any help would be appreciated.
Thanks.
Can you put some code in the viewWillDisappear method? You're not clear on why you actually want to observe the variable. However this method will be called just before the view moves off. Conversely you can run code in the viewDidDisappear which is run after the view pops.

console warning when presenting a viewController

i'm working on an app that display a viewController when is rotated to the left and then when it's rotated to the right, it displays another view controller. my segue's style is modal and i'm using the cross dissolve transition. the problem is when i rotate left then quickly rotate to the right, the console sends me this warning:
Warning: Attempt to present <SSGraphRightViewController: 0x81159b0> on <UINavigationController: 0x82439a0> while a presentation is in progress!
is there a way to avoid this warning? maybe accelerating the time of transition timing?
You cannot present a view controller from a view controller that is already being presented, the console is right about that so either use a different style of segue or handle it rightly.
Hope this helps : What is the difference between Modal and Push segue in Storyboards?
I had the same problem when I was trying to present a UIViewController when another UIViewController was being presented, so all I had to do was to dismiss the existing UIViewController and then present the new one. In your case it is because of the fast transition that happens during presenting a UIViewController so first dismiss the existing one and then present a new one. It should goes something like this
- (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion
In the (void) completion block put your code to present the new VC, like this:
[yourVC dismissViewControllerAnimated:YES completion:^{
//present your new VC here.
}];
Hope it helps!!.

presentViewController is disabling all removeFromSuperview messages in a UISplitViewController

Here is a visual representation of the UISplitViewController:
I'm trying to present a UIViewController (myVC) that's a subview of a UIView inside the DetailViewController of a UISplitViewController using this:
[appDelegate.splitViewController presentViewController:myVC animated:NO completion:nil];
It presents, I dismiss it, the app rotates without a hitch, then when I try to reload the detail view by clicking on a cell in the rootViewController (a UINavigationController), all the [orangeUIView removeFromSuperview] messages are mysteriously disabled (there are more orange UIViews hidden here that are inside a mainScrollView). The "INFO LABEL" in the topToolbar is updating, so I know the cell is sending data...
Why would this activity disable removeFromSuperview if presented using splitViewController? I've presented myVC using the detailViewController...
[appDelegate.detailViewController presentViewController:myVC animated:NO completion:nil];
which doesn't disable removeFromSuperview, but causes an assortment of other rotational crashes.
What's going on here?
Since this question was created as a result of a previous question, the answer to this problem was...try something else. I was unable to fix this problem by presenting a view controller, most likely because I'm using a custom UISplitViewController with a hierarchy I'd rather not get into.
Here is the solution I came up with:
Core Plot - Options on making the graph full screen - addSubview after presenting modal problems

Resources