2

I'm playing around with storyboarding in an OS X 10.10 app. I have an NSTableView that, when you click a specific row opens a segue that goes to a popover that contains an NSViewController.

How do you specify the origin NSPoint of the arrow for the popover? Right now, it just points to the NSTableView in the middle. I assumed that I could do this in prepareForSegue, but I can't seem to figure it out. prepareForSegue doesn't seem to have an understanding that the NSViewController is contained in an NSPopover

Any ideas?

Josh Barrow
  • 136
  • 2
  • 5

1 Answers1

5

You should file an enhancement request Radar for this behavior if you think it should be provided by the framework in some way.


But to workaround this in the meantime, you can create your own custom NSStoryboardSegue subclass to help with this.

@interface TablePopoverSegue : NSStoryboardSegue

@property (weak) NSTableView *anchorTableView;
@property NSRectEdge preferredEdge;
@property NSPopoverBehavior popoverBehavior;

@end

@implementation TablePopoverSegue

- (void)perform {
    if ([self anchorTableView]) {
        NSInteger selectedColumn = [[self anchorTableView] selectedColumn];
        NSInteger selectedRow = [[self anchorTableView] selectedRow];

        // If we can pick a specific row to show from, do that; otherwise just fallback to showing from the tableView
        NSView *anchorView = [self anchorTableView];
        if (selectedRow >= 0) {
            anchorView = [[self anchorTableView] viewAtColumn:selectedColumn row:selectedRow makeIfNecessary:NO];
        }

        // Use the presentation API so that the popover can be dismissed using -dismissController:.
        [[self sourceController] presentViewController:[self destinationController] asPopoverRelativeToRect:[anchorView bounds] ofView:anchorView preferredEdge:[self preferredEdge] behavior:[self popoverBehavior]];
    }
}

@end

This can be specified in IB in the inspector panel for the segue (just like iOS):

Segue Inspector Panel in IB

And then in your source view controller's prepareForSegue:, you can just set up the segue:

- (void)prepareForSegue:(NSStoryboardSegue *)segue sender:(id)sender {
    if ([segue isKindOfClass:[TablePopoverSegue class]]) {
        TablePopoverSegue *popoverSegue = (TablePopoverSegue *)segue;
        popoverSegue.preferredEdge = NSMaxXEdge;
        popoverSegue.popoverBehavior = NSPopoverBehaviorTransient;
        popoverSegue.anchorTableView = [self tableView];
    }
}
Taylor
  • 3,183
  • 17
  • 18