presentViewController is disabling all removeFromSuperview messages in a UISplitViewController - ios

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

Related

Visual artifact when dismissing more than one modal view controller at once

I've been struggling to find an answer to this question. I build a stack of modals via:
[[[NavA viewControllers] objectAtIndex:0] presentViewController:NavB animated:YES completion:NULL];
[[[NavB viewControllers] objectAtIndex:0] presentViewController:NavC animated:YES completion:NULL];
When I want to dismiss the NavA and NavB modals simultaneously I call
[[[NavA viewControllers] objectAtIndex:0] dismissViewControllerAnimated:YES completion:NULL];
This works fine except there's a brief flash where you can see NavB as the full stack is dismissed.
I stepped through the debugger and it looks like before the animation begins NavC disappears instantly and NavB dismisses with animation.
Is there any way to avoid this visual artifact and have the whole stack dismiss smoothly with NavC visible for the full duration of the animation?
Edit: To clarify, I'm presenting UINavigationController rather than UIViewController because this flow is for user login and has multiple possible branches that can lead back either to the current stage e.g. NavC (LoginPage), NavB (LandingPage with login and signup buttons) or all the way back to the root, NavA (main page of the application). In the iOS documentation they present a similar design pattern with the camera where each stage presents a UINavigationController with multiple possible view controllers https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/ModalViewControllers/ModalViewControllers.html
Actually there's no way to do it by just using dismissViewControllerAnimated:completion: method no matter where you put it or how you call it (at least I couldn't, if someone knows a way - we all want to know).
HOWEVER, there's a hack you can use to achieve your desired outcome (this code should be called from "B" ViewController):
// Snapshot of "C" ViewController
UIGraphicsBeginImageContextWithOptions([UIScreen mainScreen].bounds.size, YES, 0);
UIView *snapshot = [self.presentedViewController.view snapshotViewAfterScreenUpdates:NO];
UIGraphicsEndImageContext();
// Cover the entire view of "B" (and hide navigation bar)
[self.view addSubview:snapshot];
self.navigationController.navigationBarHidden = YES;
// Dismiss "C" without animation
[self.presentedViewController dismissViewControllerAnimated:NO completion:^{
// Dismiss "B" with animation
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}];
If you are using a Storyboard then this should be achievable using Unwind Segues. Mike Woelmer has a good set of articles about this. Basically you provide information to the Storyboard about how a view can unwind through several different views to get a to a view that's already on the stack.
However, I'm a bit confused in the same way that Jeffery Thomas is in the comments: why are you presenting a navigation controller with another navigation controller? I can understand that you might want the navigation bar to look different on different views, but you can customise that when the view is due to appear. You should think a bit about the content of the views in NavB and NavC and ask yourself whether they are supposed to be presented as modal views or whether they would be better off as part of a single navigation stack. By presenting each Navigation Controller modally you're ending up with multiple navigation stacks, not a single stack with multiple view controllers. Even if just NavB and NavC were part of the same stack it would probably remove the visual glitch you're seeing.
If you did use a single navigation controller then you can get back to a previous view controller in the navigation stack by using the method -popToViewController:animated: on UINavigationController.
If you decide that presenting NavB and NavC modally as you are currently doing is the right thing to do then you are likely to get into trouble because when you ask NavA to dismiss its view controller it will try to dismiss NavB, which to it means setting up a transition between the NavB's view and NavA's view. That's why you're seeing that transition, and not the one you want (which is between NavC's view and NavA's). One way which might work (and sounds a bit weird) is to try to present NavA from NavC, then override the transition to make it look like you're popping NavC off the stack. Once you're there you can clean things up by removing any strong references to NavB and NavC. This article from Ash Furrow will get you most of the way.
You can fake the animation to look exactly as you wish:
pop/dismiss B and C without animation
push/present C without animation
pop/dismiss C using whatever animation you wish

Two Modal VC are displayed simultaneously ios

For some reason, when I try to open a view controller via modal segue, it opens up two of the same type. Why is this happening?
Warning: Attempt to present <ModalViewController: 0x7fa062c5edd0>
on <HomeViewController: 0x7fa062e16e40> which is already presenting
<ModalViewController: 0x7fa062fb9780>
This is causing problems because I try to use delegates, but my main view controller never gets the correct delegate.
The issue occurs when I click the the button which triggers showModalView
HomeViewController
- (IBAction)showModalView:(UIButton *)sender {
ModalViewController *modalView = [[ModalViewController alloc] init];
[self presentViewController:modalView animated:YES completion:nil];
}
I tried this solution here and here and a dozen other ones, but none seem to work for me.
Why is this happening?
The problem you're having, is because you've connected a segue to the button, and are also presenting the controller in code; you should be doing one or the other. When you removed the segue, you got a black screen because you're using alloc init to create your controller. If you made the controller in a storyboard, then you should use instantiateViewControllerWithIdentifier: instead.
However, the easier way would be to leave the segue connected to the button, and delete the code you have in the button's action method. The button doesn't need an action method, if you have it hooked directly to a segue. All of this is covered in Apple's document, "View Controller Programming Guide for iOS". You should read it.

Modal ViewController presenting another viewController won't animate immediately

Yes, I struggled a bit with that title...
Here's what my setup is meant to do:
I push a viewController (resultViewController) onto the navigation stack. Immediately (literally in the next line of code) I present another viewController to the rootViewController (filterViewController).
So far, so good, and things work as expected.
The modally presented viewController contains a tableView. Selecting a cell is supposed to present another viewController in the current (filterView) controller.
[self presentViewController:filterDetailsController animated:YES completion:^(void){
}];
This is where things go awry: The above snippets is called at the correct time, but the viewController does not appear until I perform an additional tap or gesture somewhere in the filterView. This suggest that the stacking of modalView inside modalView somehow messes things up. If I change the animated parameter to NO, the viewController is presented immediately.
An obvious work-around would be to set animated to NO and perform a manual animation in the completion block. I would however love to see if anyone have come across anything similar and knows how to fix the problem.

Unresponsive view instantiated with instantiateViewControllerWithIdentifier:

Im having some trouble with a view that I needed instantiating from a storyboard ID. In IOS simulator, the view loads with everything in place but is completely unresponsive. The date picker doesn't move and the buttons don't accept any interaction.
Ive checked the 'custom class' matches in IB and the Storyboard ID matches. The code is being executed in the PickerViewController because the UIDatePicker is being created in code and is correct and present in IOS simulator. Its just that nothing accepts any interaction. The buttons don't even go blue when touched.
I created the view in the previous view controller with:
PickerViewController *addViewController = (PickerViewController *)[self.storyboard instantiateViewControllerWithIdentifier:#"view"];
[addViewController.view setUserInteractionEnabled:TRUE];//chucked this line in to see if it helped
[addViewController setModalPresentationStyle:UIModalPresentationFormSheet];
[self presentViewController:addViewController animated:YES completion:NULL];
I'm not sure if this is a code problem, or if I've not hooked something up in IB properly. Any ideas??!!
Check your view controllers class in assistant editor:

Dismiss ViewController that is presented via Popup

So i am creating an ipad recipe based app using storyboards. Just to give you an idea of the structure of my program here is the flow of View controllers:
ViewController --Modally--> PreviewViewController --Modally-->
RecipeViewController --Popup--> IngredientsViewController
All of this has been done in storyboarding. I created the IngredientsViewController and have linked it up to the RecipeViewController to be displayed as a popup, which works fine. However i want to be able to dismiss the IngredientsViewController programatically (because i've implemented voice command features). The problem is i can't seem to access the IngredientsViewController to dismiss it. (appologies i can't yet post any pictures).
I am using the following code to present the IngredientsViewController programatically (from within RecipeViewController):
[self performSegueWithIdentifier:#"ingr" sender:nil];
Which works fine to display the popup, but i cant dismiss it. I've tried to access it through the hierarchy of view controllers but cannot seem to find it, i would assume that it would be at the top of the stack, but apparently not? I've tried things like:
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
Again this was called from within RecipeViewController. But that simply dismisses the RecipeViewController and not the IngredientsViewController that is being presented by popup.
Just to be clear the IngredientsViewController is not a UIPopoverController, it is a normal viewController created in storyboard, and its segue style is popup linked to a button in the RecipeViewController.
Any help would be greatly appreciated. Thanks!
UIPopoverController *popOver = (UIPopoverController *)self.presentedViewController;
[popOver dismissPopoverAnimated:YES];
This should do the trick if your destination view controller is a UIPopoverController
Have you tried presentViewController:animated:completion: instead of performSegueWithIdentifier:?

Resources