Делать что-то после закрытия NSOpenPanel - PullRequest
3 голосов
/ 15 октября 2011

У меня есть 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 Ответ

5 голосов
/ 15 октября 2011

Поскольку обработчик завершения панели вызывается до фактического закрытия панели, 1 одним из решений является наблюдение NSWindowDidEndSheetNotification в вашем модальном окне:

  1. Объявите переменную / свойство экземпляра в вашем классе для хранения ошибки проверки;
  2. Объявите метод, который будет выполняться, когда панель будет эффективно закрыта. Определите его так, чтобы при наличии ошибки в текущем окне;
  3. Пусть ваш класс прослушивает NSWindowDidEndSheetNotification на [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 . Я действительно не помню, должна ли ошибка отображаться на панели открытия / сохранения.

...