在NSOpenPanel关闭后做一些事情

时间:2011-10-15 02:10:03

标签: cocoa nsopenpanel nssavepanel

我有一个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];

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

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

我希望用户点击确定,打开面板表格折叠,然后显示警报表。

我想我可以使用延迟选择器来呈现警报,但这看起来像是黑客。

1 个答案:

答案 0 :(得分:5)

由于在面板有效关闭之前调用了面板完成处理程序, 1 一个解决方案是在模态窗口上观察NSWindowDidEndSheetNotification

  1. 在类中声明实例变量/属性以保存验证错误;
  2. 声明一个在面板有效关闭时执行的方法。定义它,以便if在当前窗口中显示错误;
  3. 让您的班级在NSWindowDidEndSheetNotification上听[self window],在发送通知时执行上述声明的方法;
  4. 在面板完成处理程序中,如果验证失败,则将错误分配给上面声明的实例变量/属性。
  5. 通过执行此操作,完成处理程序将仅设置验证错误。调用处理程序后不久,打开的面板将关闭,通知将发送到您的对象,这反过来会显示由完成处理程序设置的验证错误。

    例如:

    在您的班级声明中,添加:

    @property (retain) NSError *validationError;
    - (void)openPanelDidClose:(NSNotification *)notification;
    

    在您的班级实施中,添加:

    @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];
    
    }
    

    1 如果您认为此行为有误,请考虑filing a bug report with Apple。我真的不记得是否应该在打开/保存面板上显示错误。