iOS - How to check if a modal view is present - ios

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] ) {
}

Related

viewDidAppear and viewDidDisappear not called when modalPresentationStyle=UIModalPresentationCustom

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.

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.

Change tab programmatically (iOS)

I know how to change between tabs when I am currently on one of the views presented by the tab controllers, using this:
self.tabBarController.selectedIndex=1;
But right now I need to change between tabs while on a modal child view, I need the modal view to be dismissed and the other tab to be shown,
The best/proper pattern for this is to have the modal child hand off the task to its delegate as it exits. Define your own simple "myChildViewDelegate" protocol (could be a single method, even), and give the modal child a "delegate" property like so:
id<myChildViewDelegate> delegate;
When the user presses a button or whatever on the modal view, it calls a method on its delegate and the delegate dismisses the modal view and changes tabs.
Assuming you have some sort of button on the presented view controller just set that buttons target to a function in the presenting view.
-(void) someFunction {
... Code that creates the modal view controller and buttons
[modalViewController.changeTabButton addTarget: self action:#selector(changeTab:) forControlEvents:UIControlEventTouchUpInside];
[self presentViewController:modalViewController animated:YES completion:nil];
}
-(void) changeTab:(id)sender {
self.tabBarController.selectedIndex=1;
}

Some code not executing in a method called from another ViewController

My problem
I have a standard UIViewController. With the press of a button, it loads a form sheet modal view controller. When dismissing this modal view with the press of a UIBarButtonItem I call a method by doing:
ViewController *main = [[ViewController alloc] initWithNibName:nil bundle:nil];
[main updateLabel];
In the method -(void)updateLabel in the main ViewController I'm setting the text of a label, but the label won't change. But I know the function gets called, because if I do a NSLog(#"Method call test); instead of label.text = #"Test" I can see the message in console.
What am I doing wrong? It must be the way I'm calling the method in the main ViewController, because I can easily change the label anywhere else.
What I want to do:
When dismissing a modal view controller, I want a method to be called in the main view controller, and in this case change the text of a label.
Thanks for your help!
You're creating a new instance of ViewController with that code, not getting a pointer to the one you already have.
If ViewController is the controller that presented the modal view, then you can get a pointer to it with,
ViewController *main = self.presentingViewController;
A better way to do this would be to use the delegate pattern.
https://developer.apple.com/library/ios/documentation/general/conceptual/DevPedia-CocoaCore/Delegation.html
The following is a design pattern suggestion
The modal view controller shouldn't know how to dismiss itself, that is the responsibility of the presenting view controller. After all, it could have been presented in many different ways (modally, popover, push navigation). Using the delegate pattern, the modal view controller would tell its delegate that it should be dismissed when the bar button item gets pressed. The delegate, which is the presenting view controller, would then dismiss the modal view and update the label mentioned in your question.

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.

Resources