在NSOpenPanel关闭后做一些事情

ale*_*ntd 3 cocoa nssavepanel nsopenpanel

我有一个NSOpenPanel,我想在用户点击OK后对选择进行一些验证.我的代码很简单:

void (^openPanelHandler)(NSInteger) = ^(NSInteger returnCode) {
    if (returnCode == NSFileHandlingPanelOKButton) {
        // do my validation
        [self presentError:error]; // uh oh, something bad happened
    }
}

[openPanel beginSheetModalForWindow:[self window]
                  completionHandler:openPanelHandler];
Run Code Online (Sandbox Code Playgroud)

[self window]是一个应用程序模式窗口.面板将作为工作表打开.到现在为止还挺好.

Apple的文档说完成处理程序应该在用户关闭面板后调用.但在我的情况下,按下"确定/取消"按钮后立即调用,而不是在面板关闭时调用.这样做的结果是错误警报在打开的面板上方打开,而不是在面板关闭后打开.它仍然有效,但它不像Mac那样.

我更喜欢的是用户单击确定,打开面板表格折叠,然后显示警报表.

我想我可以使用延迟选择器来呈现警报,但这似乎是一个黑客.

小智 5

由于面板已经有效关闭前面板完成处理程序被调用时,1个一个解决办法就是观察NSWindowDidEndSheetNotification你的模态窗口:

  1. 在类中声明实例变量/属性以保存验证错误;
  2. 声明一个在面板有效关闭时执行的方法.定义它,以便if在当前窗口中显示错误;
  3. 让你的班级听,NSWindowDidEndSheetNotification[self window]发送通知时执行上面声明的方法;
  4. 在面板完成处理程序中,如果验证失败,则将错误分配给上面声明的实例变量/属性.

通过这样做,完成处理程序将仅设置验证错误.调用处理程序后不久,打开的面板将关闭,通知将发送到您的对象,这反过来会显示由完成处理程序设置的验证错误.

例如:

在您的类声明中,添加:

@property (retain) NSError *validationError;
- (void)openPanelDidClose:(NSNotification *)notification;
Run Code Online (Sandbox Code Playgroud)

在您的类实现中,添加:

@synthesize validationError;

- (void)dealloc {
    [validationError release];
    [super dealloc];
}

- (void)openPanelDidClose:(NSNotification *)notification {
    if (self.validationError) [self presentError:error];
    // or [[self window] presentError:error];

    // Clear validationError so that further notifications
    // don't show the error unless a new error has been set
    self.validationError = nil;

    // If [self window] presents other sheets, you don't
    // want this method to be fired for them
    [[NSNotificationCenter defaultCenter] removeObserver:self
        name:NSWindowDidEndSheetNotification
        object:[self window]];
}

// Assuming an action fires the open panel
- (IBAction)showOpenPanel:(id)sender {
    NSOpenPanel *openPanel = [NSOpenPanel openPanel];

    [[NSNotificationCenter defaultCenter] addObserver:self
        selector:@selector(openPanelDidClose:)
        name:NSWindowDidEndSheetNotification
        object:[self window]];

    void (^openPanelHandler)(NSInteger) = ^(NSInteger returnCode) {
        if (returnCode == NSFileHandlingPanelOKButton) {
            // do my validation
            // uh oh, something bad happened
            self.validationError = error;
        }
    };

    [openPanel beginSheetModalForWindow:[self window]
                      completionHandler:openPanelHandler];

}
Run Code Online (Sandbox Code Playgroud)

1如果您认为此行为有误,请考虑向Apple提交错误报告.我真的不记得是否应该在打开/保存面板上显示错误.