Popover segue documentation/tutorial?

Discussion in 'iOS Programming' started by whooleytoo, Jun 7, 2012.

  1. whooleytoo macrumors 604

    whooleytoo

    Joined:
    Aug 2, 2002
    Location:
    Cork, Ireland.
    #1
    Maybe my Google skills are failing me, but I can't find any documentation or tutorials on how to create a popover segue in Storyboard. I've found several that create a popover programmatically, but none for Storyboard.

    I tried creating a ViewController in the Storyboard, then a Popover segue to it. Link the segue's anchor to a view in the source scene (is that correct?). But when I trigger the segue, prepareForSegue: gets called, then... nothing.
     
  2. Ron C macrumors member

    Joined:
    Jul 18, 2008
    Location:
    Chicago-area
    #2
    I do have some code for a custom subclass of UISegue (or whatever it's called) that I'll post tomorrow when I'm on my computer instead of iPad.

    In the meantime, verify that the segue.destinationViewController is what you want it to be, and maybe just for grins you can change it to a modal and see if that works. If it doesn't work there something is wrong in the storyboard,
     
  3. whooleytoo thread starter macrumors 604

    whooleytoo

    Joined:
    Aug 2, 2002
    Location:
    Cork, Ireland.
    #3
    Thanks. I tried adding a button and doing a (non-conditional) popover segue from that and it worked fine. My problem was performing a segue from a button in a (custom)UITableViewCell; doesn't work for me; I get an error saying the outlet can't be compiled. If I do a conditional segue and trigger it from the cell's button, there's no error, but the popover doesn't appear either.

    So, I can't see any way of performing a popover segue from a button in a cell, either directly or via performSegue: .... It was quite easy to do so via code, so I went that route instead. Thanks again.
     
  4. Ron C, Jun 8, 2012
    Last edited: Jun 8, 2012

    Ron C macrumors member

    Joined:
    Jul 18, 2008
    Location:
    Chicago-area
    #4
    Code and hint

    A little more background. I'm not entirely sure popover segues work, and I couldn't find a simple way of doing a popover segue that would operate in the way I needed it to without building a custom UIStoryboardSegue subclass. This subclass doesn't do a lot, really, except REUSE your popover controller AND allow toggling.

    Given that it became a custom subclass, I also couldn't get any custom information into it from the storyboard, so I put that code into the prepareForSegue: handler in the view controller.

    This is what it looks like in Xcode:
    Screen Shot 2012-06-08 at 7.44.31 AM.png

    What that picture shows is a custom segue going from a bar button item to a navigation controller. It's a navigation controller because there's a sequence of table view controllers under that popover, but it can be any subclass of UIViewController.

    Here's the code:

    SinglePopoverSegue.h
    Code:
    //
    //  SinglePopoverSegue.h
    //  LTE-A Visualizer
    //
    //  Created by Ron Crocker on 1/24/12.
    //  Copyright (c) 2012 Nokia Siemens Networks, LLC. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface SinglePopoverSegue : UIStoryboardSegue
    
    @property (strong) UIPopoverController *popoverController;
    @property (strong) UIBarButtonItem *barButtonItem;
    @property (assign) UIPopoverArrowDirection popoverArrowDirections;
    @property (assign) BOOL animated;
    @property (assign) BOOL toggleMode;
    @end
    
    SinglePopoverSegue.m
    Code:
    //
    //  SinglePopoverSegue.m
    //  LTE-A Visualizer
    //
    //  Created by Ron Crocker on 1/24/12.
    //  Copyright (c) 2012 Nokia Siemens Networks, LLC. All rights reserved.
    //
    
    #import "SinglePopoverSegue.h"
    
    @implementation SinglePopoverSegue
    
    @synthesize popoverController;
    @synthesize popoverArrowDirections;
    @synthesize animated;
    @synthesize barButtonItem;
    @synthesize toggleMode;
    
    -(id)initWithIdentifier:(NSString *)identifier source:(UIViewController *)source destination:(UIViewController *)destination
    {
        if ((self = [super initWithIdentifier:identifier
                                       source:source
                                  destination:destination])) {
            self.popoverArrowDirections = UIPopoverArrowDirectionAny;
            self.popoverController = nil;
            self.animated = YES;
            self.barButtonItem = nil;
            self.toggleMode = YES;
        }
        return self;
    }
    
    -(void)perform
    {
        if (!self.popoverController.popoverVisible) {
            self.popoverController.contentViewController = self.destinationViewController;
            
            [self.popoverController presentPopoverFromBarButtonItem:self.barButtonItem
                                           permittedArrowDirections:self.popoverArrowDirections
                                                           animated:self.animated];
        } else if (self.toggleMode) {
            [self.popoverController dismissPopoverAnimated:self.animated];
        }
    }
    
    @end
    
    The place where it's used in a view controller:
    Code:
    #pragma mark - UIStoryboard handlers
    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
        if ([segue.identifier isEqualToString:@"ConfigButton"]) {
            UINavigationController *navController = segue.destinationViewController;
            
            LAVSettingsController *vc = [navController.viewControllers objectAtIndex:0];
            
            SinglePopoverSegue *popoverSegue = (SinglePopoverSegue *)segue;
            
            if (!__popoverController) {
                __popoverController = [[UIPopoverController alloc] initWithContentViewController:popoverSegue.destinationViewController];
            }
            popoverSegue.barButtonItem = sender;
            popoverSegue.popoverController = self.popoverController;
            vc.popoverController = self.popoverController;
            
            [self.popoverController setContentViewController:navController];
        }
    }
    
    So you can see from the code in prepareForSegue: that I can't get enough information into the segue in IB, so I have to do it here. In particular, I can't get (or find) the "source" element, the place from which the popover originates, which is an important aspect of a UIPopoverController.

    EDIT: it's not entirely obvious that __popoverController is the backing store for the popoverController property. It's got 2 underscores because UIViewController already has a property called _popoverController but I can't actually get access to that to store MY popover controller. This is probably a risky use of the name, but whatever. If it becomes a problem, I'll deal with it then.
     
  5. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #5
    Maybe you could call it _myPopoverController. :)
     
  6. Ron C macrumors member

    Joined:
    Jul 18, 2008
    Location:
    Chicago-area
    #6
    Good point. Perhaps I should deal with that now. At some point in the future I won't be able to remember why it has 2 underscores...
     

Share This Page