viewDidAppear and viewDidDisappear not called when modalPresentationStyle=UIModalPresentationCustom - ios

I need to do a custom presentation animation and when i set both these setTransitioningDelegate and modalPresentationStyle=UIModalPresentationCustom
The animation is perfect with unless the viewDidAppear and viewDidDisappear is not called in the presenting viewcontroller.This is same for Apple sample code in https://developer.apple.com/library/ios/samplecode/LookInside/Introduction/Intro.html
[overlay setTransitioningDelegate:[self transitioningDelegate]];
overlay.modalPresentationStyle=UIModalPresentationCustom;
[self presentViewController:overlay animated:YES completion:NULL];
Why the methods are called when no modalPresentationStyle is given?

This is the correct behaviour as presenting a new view controller only hides the presenting view controller. It doesn't add the view to the hierarchy when the presented view controller is dismissed, and it doesn't remove the presenting view controller view from the hierarchy when the view controller that is presented is presented.
Short story; it hides the view of the presenting view controller instead of removing it. Therefore the methods aren't invoked.

Related

Present View Controller is opened on ViewController's View or On Window ?

I want to know that the present view controller is opened on view or on window.
What is self representing in this Code.
[self presentViewController:imagePicker animated:YES completion:nil];
It is presented from the view controllers view.
Note that if the view controllers view is not full screen (i.e. it's a child view whose frame is only the bottom half of the screen) then you should not present from that controller. Instead, you should present from the parent controller (or, more generically, the root view controller).
it is view for window when you set window of view controller size small you can check
UIViewController is super class of all UIViewController so we can access the all available method of UIViewController.
presentViewController is method of UIViewController so we can access this method to present new view controller in our view controller.
[self presentViewController:imagePicker animated:YES completion:nil]; in this method self represent own object to access this method. due to inheritance we can access this method.

iOS: touch events are not sent to the next controller while a modal is dismissed

In my Storyboard I defined a modal segue. The corresponding modal view is dismissed via a button and a simple:
- (IBAction)dismiss:(id)sender {
[self dismissViewControllerAnimated:YES completion:^{
return;
}];
}
Everything works but the thing is, while this transition is occurring, if the user taps in the view of the "next" controller (i.e. the one that will replace the modal), touch events are not captured by this controller until the transition completes entirely.
My chain of controllers is:
UINavigationController -> visibleViewController -> modal Controller
(but note that the modal Controller is actually presented by the navigationController - that's how it is setup by default in the Storyboard).
How can you make sure that as soon as the transition starts, touch events are sent to the next controller?
What you're describing is normal iOS behavior and not Model ViewController specific. Entering or exiting ViewControllers using push and pop will also wait for transition to end before receiving touch events on the destination ViewController.
A good solution to avoid this would be to present your ViewController in a container inside the first ViewController.
Showing and dismissing the ViewController are under your responsibility and will require a bit more code (for example playing with the alpha channel of the container) but will give you more control on who and when a view receives touch events.
For example:
- (IBAction)hideContainer:(id)sender {
[UIView animateWithDuration:0.4
delay:0.0
options:UIViewAnimationOptionAllowUserInteraction
animations:^
{
self.container.alpha = 0;
}
completion:^(BOOL finished){}];
}
When you present or dismiss some view controller modally, during transitions your modal view controller's view is added by system onto transitioning view.
During dismissal, view controller which was under your modal one, is covered by a transparent transitioning view which intercepts touches, so basically there is no simple way to pass them through it.
The option could be that you override the transitioningDelegate for your modal presentation, and add some intercepting view onto the transitioning view under your modal controller's view. Intercepting view will get all your touches during transition and then you will forward them to the underlying presenting view controller's view.
e.g. during dismissal transition you would have something like this:
Modal VC View
----------------
Intercepting View
--------------------------
Transitioning View
-------------------------------------------
Presenting View Controller's view
------------------------------------------------------------------
Window
------------------------------------------------------------------------------
Then you theoretically will be able to forward your touches to the Presenting View Controller's view.

ViewDidAppear not called in main view when modal view is presented over a popover

I'm trying to use a popover as an intermediary menu between my main view and a modal view controller. I can successfully present the Modal view controller from the popover by using the following code:
UIStoryboard *storyboardiPad = [UIStoryboard storyboardWithName:#"MainStoryboard_iPad" bundle:nil];
cbwEditControlPanel *editCP = [storyboardiPad instantiateViewControllerWithIdentifier:#"EditCP"];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:editCP];
[nav setToolbarHidden:NO];
[nav setModalPresentationStyle:UIModalPresentationFullScreen];
[nav setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[self presentViewController:nav animated:YES completion:nil];
self.modalInPopover = NO;
The problem I'm running into is that when the EditCP modal view controller is dismissed, the main view controller never updates. I have a pagecontroller on the main view that should be updated to reflect the number of pages as set in the EditCP modal view controller, but for some reason the modal view controller being called from the popover prevents the main view controller from updating the pagecontroller. I've even tried calling the main view's "View Will Appear" method from the popover or modal view when they are dismissed, but even if the 'viewWillAppear' method is called the pageController will not update!
Any ideas what is preventing the pageController from updating? I even passed a reference to the pagecontroller to the modal view and tried to update it there, but it seems that from the time the popover is presented until it is dismissed, I cannot update the number of pages on the PageController.
Thank you!
So this is an old question but I also came across a similar problem recently when using a popover. My solution was to use an unwind segue to trigger my parent view to perform some action. In my case my parent view contains contact information and the popover contains a list of cites. All I wanted to do was to have the parent view update with the new city once the user selected it from the popover. So in my parent view I create my unwind function as follows:
In the .h:
- (IBAction)unwindToContactTVC:(UIStoryboardSegue *)unwindSegue;
In the .m:
- (IBAction)unwindToContactTVC:(UIStoryboardSegue *)unwindSegue
{
[self updateTableForOffice];
}
In the above .m file is where you would have the logic to do whatever it is you want to in the parent view. To connect this unwind segue go to the child view in the storyboard and control drag from the view icon to the exit icon. You should see a pop up with the name of your unwind segue.
Finally, give that unwind segue a name and then in the child controller in the viewWillDisappear() function call the segue as follows:
- (void)viewWillDisappear:(BOOL)animated
{
[self performSegueWithIdentifier:#"unwind-to-contact-tvc" sender:self];
}
I hope that helps. If someone has a better solution let me know.
Well, I half solved the problem. The only way to get an update function when the popover disappeared was to stop using Storyboards and programmatically present the popover, using the main view as the delegate. I then was able to update correctly inside the popoverControllerDidDismissPopover method.
However, I am still interested in finding a way to update the pageControl when the modal is dismissed, before the popover is dismissed.

modal view controller not calling presenting view controller's dismissModalViewControllerAnimated: method

In my modal view controller I have a button handling method that includes
[self dismissModalViewControllerAnimated: YES];
In the presenting view controller I override dismissModalViewControllerAnimated: as follows:
-(void) dismissModalViewControllerAnimated: (BOOL)animated
{
NSLog(#"dismiss");
[super dismissModalViewControllerAnimated: animated];
}
When the button is touched, the button handling method gets called, but the dismissModalViewControllerAnimated: override does not seem to get called: the NSLog(#"dismiss"); statement isn't called, and a breakpoint inside the method doesn't get hit.
I tried
[[self presentingViewController] dismissModalViewControllerAnimated: YES];
but that didn't work either. However, the modal view controller does get dismissed.
Any idea what might be going wrong?
This is normally handled by declaring your presenting view controller as a delegate for your modal view controller. The modal VC then called a delegate method in the presenting VC to dismiss the modal transition it created.
Example:
Modal VC.h:
#protocol ModalViewControllerDelegate
-(void)dismissMyModalViewController;
#end
Modal VC.m:
// When you want to dismiss the Modal VC
[delegate dismissMyModalViewController];
Presenting VC.h:
// Make sure to #import ModalVC.h
#property (nonatomic, retain) id <ModalViewControllerDelegate> delegate;
Presenting VC.m:
-(void)dismissMyModalViewController {
[self dismissModalViewControllerAnimated:YES];
}
from Programming iOS 6, by Matt Neuburg:
On the iPad, when the presented view controller’s modalPresentationStyle is UIModalPresentationCurrentContext, a decision has to be made as to what view controller should be the presented view controller’s presentingViewController. This will determine what view will be replaced by the presented view controller’s view. This decision involves another UIViewController property, definesPresentationContext (a BOOL). Starting with the view controller to which presentViewController:animated:completion: was sent, we walk up the chain of parent view controllers, looking for one whose definesPresentationContext property is YES. If we find one, that’s the one; it will be the presentingViewController, and its view will be replaced by the presented view controller’s view. If we don’t find one, things work as if the presented view controller’s modalPresentationStyle had been UIModalPresentationFullScreen.
TL;DR
1. set definesPresentationContext to true on the desired presentingViewController
2. set modalPresentationStyle to UIModalPresentationCurrentContext on the desired presentedViewController
The code that presented the modal view controller was contained in a UIViewController, which was in turn contained in a UINavigationController. When I called
[[self presentingViewController] dismissModalViewControllerAnimated: YES];
or
[self dismissModalViewControllerAnimated: YES];
the dismissal message was being sent to the UINavigationController object.

iOS - How to check if a modal view is present

Is there a way to check if a modal view is present? I'd like to run a method only if a modal view is present. Also, if I have multiple modal views, is there a way to check if a certain modal view is present.
I use the following code to present and dismiss modal views:
[self presentModalViewController:myModalView animated:YES];
[self dismissModalViewControllerAnimated:YES];
Thank you in advance!
Cheers,
Evan
PS. My modal view has a view controller, but I'd like to check if the modal view is present from a separate class that is running asynchronously.
Are you checking the presence of a modal view controller from the parent view controller? If so, you can just check that view controller's modalViewController property:
BOOL modalPresent = (self.modalViewController);
If you want to check for a particular modal view controller, you can get the modal view controller's class name like this:
NSString *modalClassName = NSStringFromClass([self.modalViewController class]);
You can check using: self.presentedViewController, which returns The view controller that is presented by this view controller, or one of its ancestors in the view controller hierarchy.
What worked for me is following:
// this is the trick: set parent view controller as application's window root view controller
UIApplication.sharedApplication.delegate.window.rootViewController = viewController;
// assert no modal view is presented
XCTAssertNil(viewController.presentedViewController);
// simulate button tap which shows modal view controller
[viewController.deleteButton sendActionsForControlEvents:UIControlEventTouchUpInside];
// assert that modal view controller is presented
XCTAssertEqualObjects(viewController.presentedViewController.class, MyModalViewController.class);
As far as I tested it, this works for iOS7 and iOS8. Didn't try on iOS6 however.
You can check the presence of a modal view controller from the parent view controller
if ( [[self presentingViewController] presentingViewController] ) {
}

Resources