How to Close NSPopover programmatically
Asked Answered
E

4

2

I want to know how to close NSPopover programmatically, not by touching outside, because I want to assign it to an action (such as KeyDown Enter Key or other shortcut)

because I open my NSPopover with a shortcut, it would be more logical to close by pressing another command

going to share my code:

EdiciondeCuentasWC.h (NSWindowController) from where I call my NSPopover

#import "EdicionDeCuentasWC.h"
#import "CambiarTipoCuentaVC.h"
@interface EdicionDeCuentasWC ()<NSPopoverDelegate>{
    CambiarTipoCuentaVC         *cambiarTipoCuentaVC;
}
@property (strong) IBOutlet NSPopover *popoverClasifCuentas;

@end


@implementation EdicionDeCuentasWC

-(void)mostrarPopupCambiarTipoCta{

        cambiarTipoCuentaVC = (CambiarTipoCuentaVC *) _popoverCambiarTipoCuentas.contentViewController;
        cambiarTipoCuentaVC.nombre_tipo_cta  = arrayActivos[renglonSeleccionado][@"nombre_tipo_cta"];
        cambiarTipoCuentaVC.prioridad_cta    = arrayActivos[renglonSeleccionado][@"prioridad_cta"];

        NSTableCellView *cellView = [_activoTableView viewAtColumn:0
                                                               row:renglonSeleccionado
                                                   makeIfNecessary:NO];

        [_popoverClasifCuentas      setDelegate:self];
        [cambiarTipoCuentaVC        inicializarDatos];
        [_popoverCambiarTipoCuentas showRelativeToRect:[cellView bounds] ofView:cellView preferredEdge:NSMaxXEdge];
}

#pragma mark NSPopoverDelegate
-(void)popoverWillClose:(NSNotification *)notification{

    NSPopover *popover = (NSPopover *)[notification object]; //there I have the code for managing all the returning parameters...

}

@end

And the code of my NSPopover is inside of a NSViewController (CambiarTipoCuentaVC) but inside there I there's neither [self close] nor [self performClose] for making it close from a button, or shortcut, any help to make it work I'd appreciate...

Esthete answered 5/8, 2014 at 23:23 Comment(0)
J
9

In the NSPopover documentation, there is described a -close method and, for a slightly different purpose, -performClose: method.

Jaquelynjaquenetta answered 6/8, 2014 at 0:6 Comment(2)
the thing is... I have all my programming inside a NSViewController and there is neither [self close] nor [self performClose] going to upload my codeEsthete
Messages don't have to go to self. Given that you have a reference to the popover, you can send it a message using that reference.Jaquelynjaquenetta
S
19

I came across this post and wanted to share my solution.

>macOS 10.10, Swift 4

Since macOS 10.10 you can call

presentViewController(_ viewController: NSViewController, asPopoverRelativeTo positioningRect: NSRect, of positioningView: NSView, preferredEdge: NSRectEdge, behavior: NSPopoverBehavior)

on NSViewController to present another View Controller as a popover.

When you do that, the presenting View Controller is available via the presenting property. Thus, you only need to call presenting?.dismissViewController(self) to dismiss the popover.

I hope that's helpful for anyone looking for a modern solution to this problem.

Stick answered 24/2, 2017 at 19:45 Comment(1)
In Swift 4.2, it's presentingViewController?.dismiss(self) but otherwise, thank you for this - I'm finding it smoother and just a trifle faster than my solution.Hamal
J
9

In the NSPopover documentation, there is described a -close method and, for a slightly different purpose, -performClose: method.

Jaquelynjaquenetta answered 6/8, 2014 at 0:6 Comment(2)
the thing is... I have all my programming inside a NSViewController and there is neither [self close] nor [self performClose] going to upload my codeEsthete
Messages don't have to go to self. Given that you have a reference to the popover, you can send it a message using that reference.Jaquelynjaquenetta
H
3

What you want to close is the window of your popover, so you can simply add

@IBAction func closePopover(_ sender: Any) {
    self.view.window?.performClose(sender)
}

to your popover's view controller, no subclassing needed.

(Xcode 10, macOS 10.13, Swift 4.1)

edited to add: I've now tried JanApotheker's solution using presentingViewController?.dismiss(self), and it's just that bit faster and smoother than mine, so I no longer recommend it.

Hamal answered 14/6, 2018 at 16:4 Comment(1)
This was hard to find, but I'm most grateful.Petterson
E
2

I found how, Im going to complement ken Thomases's Answer

I created a subclass of NSPopover called MyNSPopover

then I added next code:

#import "MyNSPopover.h"

@implementation MyNSPopover

-(void)keyDown:(NSEvent *)theEvent{

    //if enter key is pressed, the NSPopup will be closed
    if (theEvent.keyCode == 36) {
        [self close];
    }
}

@end

and then just added this class to my NSPopover like this

enter image description here

done just works

Esthete answered 6/8, 2014 at 17:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.