17

When clicking on a rightBarButton, a UIPopoverController will present.

The problem is: when clicking on the NavigationBar, this UIPopoverController does not dismiss.

Why? And is there a way to resolve it? I have tried to search, but can't find anything about this.

Thanks in advance.

Lyon_Xu
  • 233
  • 2
  • 9

6 Answers6

30

UIPopoverController seems to add the navigation bar to its passthroughViews array when it is presented. I was able to solve the problem by re-setting passthroughViews to an empty array immediately after presenting the popover.

Brian Croom
  • 325
  • 3
  • 5
  • works perfectly! Thanks, this question has been asked several times in slightly different forms and this is by far the quickest and cleanest solution. well done. – Robert Wagstaff Dec 03 '12 at 04:33
  • Instead of setting it with an empty array just set it with nil. – Ashwani Feb 21 '13 at 07:17
  • Why this is the case I do not understand. – Trebor Sep 04 '13 at 13:54
  • After a refactor in our code using passthrough views, it stopped working for some reason. I was pretty baffled as to what had changed, short of re-ordering a bit. Stumbling across this answer reminded me that the ordering was important for this. Big note around that in our code now :) – shortstuffsushi Aug 19 '14 at 17:57
  • 3
    On iOS8 you need to set passthroughViews not on the line after presenting, but in another run loop. See [this link](http://blog.karmeye.com/2014/11/20/ios8-popovers-and-passthroughviews). – Karmeye Nov 27 '14 at 06:16
  • 3
    @Karmeye Updated link: http://karmeye.com/2014/11/20/ios8-popovers-and-passthroughviews/ – jszumski Jun 23 '15 at 15:01
  • Looks like it nil by default on iOS11. – nemissm Jun 19 '18 at 03:18
5

When launching from a bar button you can simply do this

[popoverController presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
[popoverController setPassthroughViews:nil];
Catalin
  • 1,821
  • 4
  • 26
  • 32
1

Items on your navigation bar will be automatically added to popoverViewController's passthroughViews. It happens after the popover shows up. So you need to clear passthroughViews after that.

And for iOS 8, we can get popoverController from UIViewController.popoverPresentationController, before that, we can get popoverController from UIStoryboardPopoverSegue.

In your view controller presents a view controller as popover.

var popoverController: UIPopoverController?

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    // Before IOS8, we need to get reference of popOverController from UIStoryboardPopoverSegue
    if (!self.respondsToSelector(Selector("popoverPresentationController"))) {
        if let popoverController = (segue as? UIStoryboardPopoverSegue)?.popoverController {
            let menuViewController = segue.destinationViewController as AIMSMenuTableViewController
            menuViewController.popoverController = popoverController
        }
    }
}

In your view controller that is presented as popover.

var popoverController: UIPopoverController? 

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    // Set passthroughViews to nil make tapping other navigation bar button
    // dismiss presenting popoverController
    if (self.respondsToSelector(Selector("popoverPresentationController"))) {
        self.popoverPresentationController?.passthroughViews = nil
    } else {
        // For iOS8-pre version, we need to pass popoverController reference from segue
        self.popoverController?.passthroughViews = nil
    }
}
hufeng03
  • 404
  • 5
  • 9
0

The documentation for UIPopoverController states:

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.

The navigation bar is added as one of the passthroughViews when the popover is presented from a bar button item.

Perhaps try settings an empty array as the passthroughViews property on your popover controller.

Jasarien
  • 58,279
  • 31
  • 157
  • 188
  • Sorry, I set the passthroughViews to empty array, but it doesn't work. – Lyon_Xu May 27 '11 at 01:25
  • Hm, it sounds like maybe the navigation bar is the popover view controller's parent, and might be added to whatever array you set as the passthrough views... – Jasarien May 27 '11 at 09:15
0

You put this cod on any other action or After completing the selection or provide some close button in the popover and accomplish uy yhing,

[popOverControllerObj dismissPopoverAnimated:YES];
EXC_BAD_ACCESS
  • 2,699
  • 2
  • 21
  • 25
  • I can do this. But the problem is: when i tap on the back button in the NavigationBar, the parentViewController will be presented, but the popover is also there. I just want it dismissed. – Lyon_Xu May 27 '11 at 01:32
0

This is expected behavior as far as I can tell. The popover on the bookshelf in iBooks behaves like this. Retain a reference to the popover when you present it, and then dismiss it if any of the buttons in the navigation bar are tapped.

Russell Ladd
  • 341
  • 3
  • 4