I am using UIPopViewController in iPad application,I can dismiss popviewcontroller using tap on screen.But,I am trying to call function for dismiss,is that possible?How can I call function?Please help me.
If you are trying to dismiss the popover programatically, you can simply call:
[popover dismissPopoverAnimated:YES];
If you are trying to detect whether a user has dismissed a popover by tapping on the screen, you can make use of the UIPopoverControllerDelegate method popoverControllerDidDismissPopover:
First, set the viewController which presents the popover as delegate:
popover.delegate = self;
Then implement the method:
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
//Perform necessary action here.
}
Have a look at the UIPopoverControllerDelegate reference here.
Related
In my universal iOS 8 app, I am presenting a popover using using UIPopoverPresentationController as seen below from prepareForSegue:
FavoriteNameViewController *nameVC = segue.destinationViewController;
UIPopoverPresentationController *popPC = nameVC.popoverPresentationController;
popPC.delegate = self;
And with this delegate method.
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
return UIModalPresentationNone;
}
In this particular case, I'm presenting a view controller that looks like an alert, but isn't.
Now my issue is that the user can click outside of this popover and it gets dismissed. There's no real problem with that except that's not how alerts work and I would like this to emulate an alert.
I see that UIPopoverControllerDelegate had a method called popoverControllerShouldDismissPopover:, but UIPopoverPresentationControllerDelegate doesn't have that method, and I believe I need to use the latter.
You need to set the popover controller's passthroughViews to nil and the view controller's modalInPopover to YES.
Try the following in your view
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
return YES;
}
When a user taps outside the popover, the dismissal is animated. Is there a way to set that dismissal animation to NO? I have googled and searched on Stack extensively.
The docs for UIPopover state:
When displayed, taps outside of the popover window cause the popover
to be dismissed automatically. To allow the user to interact with the
specified views and not dismiss the popover, you can assign one or
more views to the passthroughViews property. Taps inside the popover
window do not automatically cause the popover to be dismissed. Your
view and view controller code must handle actions and events inside
the popover explicitly and call the dismissPopoverAnimated: method as
needed.
I have implemented the dismissPopoverAnimated: method with NO and that works great for all the cases when I call that method.
The problem is when a user taps outside the popover to dismiss, dismissPopoverAnimated: is not called.
taps outside of the popover window cause the popover
to be dismissed automatically.
And that dismissal is animated. There seems to be no way to control that dismissal. I am using the popover to present a color picker for a drawing app. Taps to draw are not registered until the popover has finished animating out. This creates a noticeable delay as you are not able to draw immediately but must wait for the animation to complete.
I thought that - (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController could work but there is no way AFAIK to set the animation property in this method. Just return yes or no.
Is there a different method I can implement to be able to set the animation to NO?
In the view controller that presents your UIPopoverController, conform to the UIPopoverControllerDelegate protocol and implement the following delegate method. I just tested this and it does dismiss the popover without animation.
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
[self.myPopoverController dismissPopoverAnimated:NO];
return YES;
}
Just make sure that you have set the delegate of your popover controller to the view controller that implements this.
Swift 5
This will disable the animation, when we close the popOver by tapping outside.
extension YourViewController: UIPopoverPresentationControllerDelegate {
func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool {
// to prevent animation, we need to dismiss it manuallly with animated: false
presentationController.presentingViewController.dismiss(animated: false, completion: nil)
return true
}
}
On iOS 9+ as by default modalPresentationStyle = .Popover you can implement this method to prevent dismiss clicking out
public func popoverPresentationControllerShouldDismissPopover(_ popoverPresentationController: UIPopoverPresentationController) -> Bool {
return false
}
As part of my updating my apps to replace the deprecated presentModalViewController with presentViewController, I did some testing.
What I found was disturbing. Whereas presentModalViewController always works and there is no question about it working, I have found the presentViewController method often will not display my VC at all. There is no animation and it never shows up.
My loadView are called without problems, but the actual view does not appear.
So here is what I am doing:
User taps a button in my main view controller.
In the callback for that tap, I create a new view controller and display it as shown above.
The VC never appears (it is an intermittent problem though) but because this VC begins playing some audio, I know that its loadView was called, which looks like as follows.
My button-pressed callback is as follows:
- (void) buttonTapped: (id) sender {
VC *vc = [[VC alloc] init];
[self presentViewController: vc animated:YES completion: nil];
[vc release];
}
Here is my loadview in the VC class:
- (void) loadView {
UIView *v = [UIView new];
self.view = v;
[v release];
... create and addsubview various buttons etc here ...
}
Thanks.
Make sure the controller that calls the function has its view currently displayed (or is a parent to the one currently displayed) and it should work.
I have a button in my popover controller. I want to use it to dismiss the popover, so I am trying to access a method (dismissPopover) of the presenting view controller (the "root" view controller).
Note: the method to dismiss the popover is already set up and working, in the root VC, which is the delegate. If I call it it will dismiss the popover. I just need to access the method from the popover.
To do this I set up a property in the AppDelegate, and get an instance of the rootVC like this: self.rootController = (ViewController*)self.window.rootViewController;. Then I imported the root VC class and the AppDelegate to the popover's view controller's class, as below. Seems to give me access to the rootVC, and the methods, but the results do not fire the method. Any idea what I am missing here?
#import "ViewController.h"
#import "AppDelegate.h"
Action connected to button:
- (IBAction)dismissPopover:(id)sender {
//Checking the button works, it does:
NSLog(#"dismissPopover, from popover");
//Trying to get an instance of the rootViewController, the "presenting view controller"
ViewController *rootVC = [(AppDelegate *)[[UIApplication sharedApplication] delegate] rootController];
//trying to access the method in the rootVC that dismisses the popover
[rootVC dismissPopover];
//Tried the following code, does nothing:
//[self dismissPopoverAnimated:YES];
}
NOTE: I ended up abandoning the use of a popover for this as it became a bit over complicated. I tried loading my view controller into a UIView (so I could load the contents of a nib to a pop-up view). That also became a bit complicated. So, for now I am just building my desired interface in a UIView programatically. So far works great.
dismissPopoverAnimated: is a method of UIPopoverController class. so, you need a popover controller reference in your 'root' view controller.
MyRootViewController.myPopoverController = thePopover;
the button is in your 'root' view controller, and in it's action method:
[self.myPopoverController dismissPopoverAnimated:YES];
In iOS 8, you can dismiss the popover (if it's coming from a segue, at least) with dismissViewControllerAnimated:completion: from within the popover. Doesn't work in iOS 7 (or below), however.
Popover automatically dismissed when clicking outside it , as you order a button to dismiss it you can simply use the following code inside your dismissPopover method :
[self.popoverController dismissPopoverAnimated:YES];
you don't need all this tedious work !
[self dismissViewControllerAnimated:YES completion:nil];
is the solution;
you just need an IBoutlet or add target to your button and then call above line
I had the same problem
just do in your buttonClickMethod:
[yourPopoverController dismissPopoverAnimated:YES];
hope you help!
cheers
I have a Settings popover. I have a button (More Info) in that popover. When the user clicks on that button, I want to bring up another view and I want to dismiss the popover.
How do I do this from my More Info button that is actually inside the popover?
Current I have a function that handles the button press:
- (IBAction)showFullVersionInfo:(id)sender
{
[self dismissPopoverAnimated:YES];
parent.settingsPopover = nil;
//need to show more Info...
}
The parent holds a reference 'settingsPopover' to the popover and I want to clear it.
You don't want to do this from inside the popover controller. The popover controller should manage only the contents of your popover, not how and when the popover is shown/hidden.
You can do such actions only in the parent controller. Hide the popover only from the controller which has shown it (and owns it).
Your question should actually be: how to tell the parent controller that the user has performed some action inside the popover?
And the answer is: delegate.
Define a delegate, implement it in your parent controller, pass it to your popover and in IBAction call delegate method.
The best way is to release popover in popoverControllerDidDismissPopover: delegate callback. Unfortunately this callback doesn't call after dismissPopoverAnimated:. I solved this by entering another unified callback named for example popoverDidFinishWorking:. Send it from popover to owner when close button was tapped, etc. When owner get popoverDidFinishWorking: it just invokes popoverControllerDidDismissPopover: and hides/release the popover (settingsPopover). You also can show any other view in this callback. Anyway it depends on your app design.
In your 'parent' object in the function where you launch the settingsPopover you should have :
- (void) launchDismissSettingPopover {
if (settingPopover == nil) {
//Create an launch the popover
} else {
[self dismissPopoverAnimated:YES];
// settingPopover will be nil in navigationController didShowViewController
//self.settingsPopover = nil;
}
}
You should have self.navigationController.delegate = self before in your parent class
-(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (viewController == self && self.settingPopover != nil) {
//need to show more Info based on settingPopover info here
self.settingPopover = nil ;
}
}
Then in your popover class method
- (IBAction)showFullVersionInfo:(id)sender
{
[parent launchDismissSettingPopover];
}