I have a view controller B which is presented as a popup by another view controller A. View controller B conforms to protocol UIPopoverPresentationControllerDelegate (defined in its header file) and implements this method.
- (void)popoverPresentationControllerDidDismissPopover:(UIPopoverPresentationController *)popoverPresentationController
{
DDLogDebug(#"Clicked outside");
}
In view controller A, I initialize view controller B, set its modalPresentationStyle to UIModalPresentationPopover and present it using the method presentViewController:animated:completion:.
When I dismiss the popover by clicking next to it, I am not receiving any notification. Why is view controller B not receiving this notification?
The same thing happens when I make view controller A conform to UIPopoverPresentationControllerDelegate and implement the method there.
I am using Objective C and target for iOS 9.
EDIT
Thanks to the comments below, I found the mistake. I forgot to set the delegate. I now set the delegate in view controller A to itself, and let A retrieve the data that it needs from view controller B.
datePickerContentViewController.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popoverController = [datePickerContentViewController popoverPresentationController];
popoverController.delegate = self;
[self.parentViewController presentViewController:datePickerContentViewController animated:YES completion:nil];
Related
I am presenting a view controller modally using this code :
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
SubmitAYoNViewController *ivc = [storyboard instantiateViewControllerWithIdentifier:#"SubmitAYoN"];
[ivc setModalPresentationStyle:UIModalPresentationFullScreen];
[self presentViewController:ivc animated:YES completion:nil];
Then in my SubmitAYoNViewController I have this:
NSLog(#"%#",self.parentViewController);
if([self.parentViewController isKindOfClass:[YesOrNoViewController class]]) {
NSLog(#"do something");
}
self.parentVeiwController is NULL. Why is that?
EDIT : I want to access a method from my parent view controller, then one that the SubmitAYoN was opened from.
SOLUTION : I used delegates instead. As per answers below, the presentViewController does not create a parent-child relationship.
If you want the presenting view controller, then use self.presentingViewController. self.parentViewController returns the controllers parent which will be nil when it is not a child of another controller.
So use:
NSLog(#"%#",self.presentingViewController);
if([self.presentingViewController isKindOfClass:[YesOrNoViewController class]]) {
NSLog(#"do something");
}
From the documentation for presentViewController:
This method sets the presentedViewController property to the specified
view controller, resizes that view controller's view based on the
presentation style and then adds the view to the view hierarchy.
So no mention of the controller being made a child as it is the view that is added to the existing view hierarchy.
You would have been ok prior to iOS5. The documention for property parentViewController states:
Prior to iOS 5.0, if a view did not have a parent view controller and
was being presented, the presenting view controller would be returned.
On iOS 5, this behavior no longer occurs. Instead, use the
presentingViewController property to access the presenting view
controller.
self.parentViewController is something you presented from this viewcontroller or self.navigationgtionController
So when you are presenting a viewcontroller where you hold an instance of the `viewcontroller' will have self.parentViewController.
I create and present UIActivityViewController in my app with custom UIActivity items in it.
When I tap UIActivity icon, UIActivityViewController slides down and my modal view controller is presented. However, when I dismiss my VC, UIActivityViewController shows up.
How can I make it disappear and never shows up again when activity item is pressed?
You need to call the activityDidFinish: method on the chosen UIActivity.
From the docs for UIActivity activityDidFinish::
Discussion
This method dismisses the sharing interface provided by the UIActivityViewController object. If you provided a view controller using the activityViewController method, this method dismisses that view controller too.
You must call this method after completing the work associated with this object’s service. This is true regardless of whether you used the activityViewController or performActivity method to initiate the service. When calling the method, use the Boolean value to indicate whether the service completed successfully.
Let's say when Activity A is chosen from UIActivityVC, you want to present modal view controller M on your current view Controller C .
If you implement A's -(UIViewController*)activityViewController method, you need to call [A activityDidFinish] in your modal view controller M's dismiss method;
If you implement A's -(void) performActivity method, it's impossible to present modal view , because current view controller C is in the process of dismissing UIActivityVC .
I think the final solution is a bit tricky. My basic idea is to subclass UIActivityViewController and override -(void) viewDidDisappear method. Thus you can do whatever you like( i.e present your own modal view,or push a sequence of other view controllers) on your current view controller C.
i found this by Ethan Huang
[self presentViewController: activityController animated: YES completion:nil];
activityController.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popPC = activityController.popoverPresentationController;
popPC.barButtonItem = saveBtn;
popPC.permittedArrowDirections = UIPopoverArrowDirectionAny;
read all about it here :
http://getnotebox.com/developer/uiactivityviewcontroller-ios-8/
In all view controllers I present a ModalViewController after I dismiss modal view controller I want to call a method in current view controller.
I have to presentModalViewController I cant push it because it is a form sheet. Since I cant push it (void)viewDidAppear:(BOOL)animated is not called when I dismiss the form sheet.
Btw form sheet is a settings menu and I have to call it in every view controller, so I cant use notifications because there are over 20 View controllers and only one settings menu;
Navigation controller -> Root- > VC1 - > VC2 - > VC3 ->VC4........... VC20......
| | | | |
Menu Menu Menu Menu Menu
I present menu:
UIStoryboard* sb = [UIStoryboard storyboardWithName:#"MainStoryboard"
bundle:nil];
SettingsListViewController *settingsVC = [sb instantiateViewControllerWithIdentifier:#"SettingsListViewController"];
UINavigationController *modalViewNavController= [[UINavigationController alloc] initWithRootViewController:settingsVC];
modalViewNavController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
modalViewNavController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:modalViewNavController animated:YES];
I dismiss it :
//dissmiss view
[self.navigationController dismissModalViewControllerAnimated:YES] ;
In View Controllers I want to Call;
[self.navigationController popToRootViewControllerAnimated:NO];
Is there a way to call a method in View Controller when form sheet is dismissed ?
Since iOS 5, you can use the presentingViewController property of every UIViewController to see 1) if they're being presented modally in the first place and 2) who it is that's presenting them modally then. So if you present your form sheet by calling [self.navigationController presentModalViewController:modalViewNavController animated:YES], the presenting view controller will then be the root navigation controller and you can tell it to pop to root at the same time you dismiss the modal presentation.
By the way, there's also a storyboard property in every view controller which has originated from a storyboard, so you could use that one directly when instantiating new storyboard view controllers by name.
Make your own delegate and set the view controller that presents the view as delegate.. and call from modalVC when it is about to be dismissed.
You can set modalViewController.parentViewController = self; and then work with it from modal view controller like that if you want to send messages before dismiss:
- (void)viewWillDisappear:(BOOL)animated {
[self.parentViewController doSomething];
}
I have a view controller B in a parent view controller A. Both views are showing the same time.
In view controller B, I'm trying to present a new view controller using the following method:
- (void) buttonClicked:(id)sender
{
MyViewcontroller *vc = [[MyViewcontroller alloc] init];
[self presentViewController:vc animated:YES completion:nil];
}
The view controller appears correctly in iOS6 and I dismiss MyViewController by using the following method:
- (IBAction)backButtonPressed:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
But there is a difference between iOS 5.1 and iOS 6.
QN1: Upon dismissal, view controller A & B viewDidAppear are not invoked. Is it supposed to be triggered?
QN2: I can't get MyViewController to show up in iOS 5.1.1. unless I add view controller B as a child container to A:
[self addChildViewController:vcB];
[self.view addSubview:vcB.view];
By adding the child controller, I can get MyViewController to show and view controller A&B viewDidAppear will be called when it gets dismissed. viewDidAppear also gets called when using iOS6.
I'm not sure what is going on here.
Answer 1 : viewDidAppear will not be called when you dismiss a modal view.
Answer 2 : if you are presenting "MyViewController" from "View-controller B" then View-controller B's view should be in view hierarchy.
From here you can get more information. How to Presenting View Controllers from Other View Controllers
I have a navigation controller named navController made programmatically in my modal view controller during its viewDidLoad:
self.navController = [[UINavigationController alloc] initWithRootViewController:self];
self.navController.view=self.view;
[self setView:self.navController.view];
But when i launch the modal view controller i dont see the navigation bar, just the standard view i made in IB. Whats wrong?
Your solution cannot work.
Suppose that you have your modal controller called ModalViewController. It's a simple UIViewController linked with a xib created interface.
Now, at some point you need to present ModalViewController modally. As you wrote in your specification, I think you want to use also a UINavigationController and control its navigation bar.
The code to do this could be the following, where presentModally could be a method that it's not contained in ModalViewController.
- (void)presentModally:(id)sender {
ModalViewController *modalController = [[ModalViewController alloc] initWithNibName:#"ModalView" bundle:nil];
// Create the navigation controller and present it.
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:modalController];
[self presentViewController:navigationController animated:YES completion: nil];
}
Now, within viewDidLoad of your ModalViewController you have access to navigationController property. In this manner you can control navigationController behaviour. For example:
- (void)viewDidLoad
{
[super viewDidLoad];
// the code changes the title for the navigation bar associated with the UINavigationController
self.title = #"Set from ModalViewController";
}
Some notes
To understand how UINavigationController works read UINavigationController class reference
To understand how modal controllers work read Modal view controllers documentation
The code I provided is a simple example and only demonstrative (I've written by hand so check for syntax). You need to make attention to memory management and how to present modal controllers. In particular, as Apple documentation suggests, to present modal controllers you need to follow these steps:
Create the view controller you want to present.
Set the modalTransitionStyle property of the view controller to the desired value.
Assign a delegate object to the view controller. Typically the delegate is the presenting view controller. The delegate is used by the presented view controllers to notify the presenting view controller when it is ready to be dismissed. It may also communicate other information back to the delegate.
Call the presentViewController:animated:completion: method of the current view controller, passing in the view controller you want to present.
Trigger (when necessary) some action to dismiss the modal controller.
Hope it helps.