3

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

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]是一个应用程序模式窗口。面板以工作表形式打开。到目前为止,一切都很好。

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

我希望用户单击确定,打开的面板折叠起来,然后出现警报表。

我想我可以使用延迟选择器来显示警报,但这似乎是一种黑客行为。

4

1 回答 1

5

由于在面板有效关闭之前调用了面板完成处理程序,因此一种解决方案是在您的模式窗口上观察NSWindowDidEndSheetNotification

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

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

例如:

在你的类声明中,添加:

@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如果您认为这种行为是错误的,请考虑向 Apple 提交错误报告。我真的不记得是否应该在打开/保存面板上显示错误。

于 2011-10-15T07:26:28.853 回答