Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>EDIT:</strong> These problems appear to be fixed as of iOS 7.1 / Xcode 5.1.1. (Possibly earlier, as I haven't been able to test all versions. Definitely after iOS 7.0, since I tested that one.) When you create a popover segue from a <code>UIBarButtonItem</code>, the segue makes sure that tapping the popover again hides the popover rather than showing a duplicate. It works right for the new <code>UIPresentationController</code>-based popover segues that Xcode 6 creates for iOS 8, too.</p> <p>Since my solution may be of historical interest to those still supporting earlier iOS versions, I've left it below.</p> <hr> <p>If you store a reference to the segue's popover controller, dismissing it before setting it to a new value on repeat invocations of <code>prepareForSegue:sender:</code>, all you avoid is the problem of getting multiple stacking popovers on repeated presses of the button -- you still can't use the button to dismiss the popover as the HIG recommends (and as seen in Apple's apps, etc.)</p> <p>You can take advantage of ARC zeroing weak references for a simple solution, though:</p> <h3>1: Segue from the button</h3> <p>As of iOS 5, you couldn't make this work with a segue from a <code>UIBarButtonItem</code>, but you can on iOS 6 and later. (On iOS 5, you'd have to segue from the view controller itself, then have the button's action call <code>performSegueWithIdentifier:</code> after checking for the popover.)</p> <h3>2: Use a reference to the popover in <code>-shouldPerformSegue...</code></h3> <pre><code>@interface ViewController @property (weak) UIPopoverController *myPopover; @end @implementation ViewController - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // if you have multiple segues, check segue.identifier self.myPopover = [(UIStoryboardPopoverSegue *)segue popoverController]; } - (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender { if (self.myPopover) { [self.myPopover dismissPopoverAnimated:YES]; return NO; } else { return YES; } } @end </code></pre> <h3>3: There's no step three!</h3> <p>The nice thing about using a zeroing weak reference here is that once the popover controller is dismissed -- whether programmatically in <code>shouldPerformSegueWithIdentifier:</code>, or automatically by the user tapping somewhere else outside the popover -- the ivar goes to <code>nil</code> again, so we're back to our initial state.</p> <p>Without zeroing weak references, we'd have to also:</p> <ul> <li>set <code>myPopover = nil</code> when dismissing it in <code>shouldPerformSegueWithIdentifier:</code>, and</li> <li>set ourself as the popover controller's delegate in order to catch <code>popoverControllerDidDismissPopover:</code> and also set <code>myPopover = nil</code> there (so we catch when the popover is automatically dismissed).</li> </ul>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload