3 Stimmen

Etwas tun, nachdem NSOpenPanel geschlossen wurde

Ich habe ein NSOpenPanel und möchte nachdem der Benutzer auf OK geklickt hat, eine Validierung der Auswahl durchführen. Mein Code ist einfach:

void (^openPanelHandler)(NSInteger) = ^(NSInteger returnCode) {
    if (returnCode == NSFileHandlingPanelOKButton) {
        // meine Validierung durchführen
        [self presentError:error]; // oh oh, etwas ist schief gelaufen
    }
}

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

[self window] ist ein anwendungsmodales Fenster. Das Panel öffnet sich als Blatt. Bisher so gut.

In Apples Dokumentation heißt es, dass der Abschluss-Handler "aufgerufen werden soll, nachdem der Benutzer das Panel geschlossen hat." Aber in meinem Fall wird er sofort beim Drücken der "OK/Abbrechen"-Taste aufgerufen, nicht nachdem das Panel geschlossen wurde. Der Effekt davon ist, dass das Fehler-Alert über dem geöffneten Panel erscheint und nicht nachdem das Panel geschlossen wurde. Es funktioniert immer noch, aber es ist nicht "Mac-like".

Was ich bevorzugen würde, ist dass der Benutzer auf OK klickt, das offene Panelblatt sich zusammenfaltet, dann das Alert-Blatt erscheint.

Ich könnte den Alert vielleicht über einen verzögerten Selektor anzeigen, aber das erscheint mir wie ein Hack.

5voto

Da der Panel-Vervollständigungshandler aufgerufen wird, bevor das Panel effektiv geschlossen wurde,1 ist eine Lösung, NSWindowDidEndSheetNotification auf Ihrem Modal-Panel zu beobachten:

  1. Deklarieren Sie eine Instanzvariable/-eigenschaft in Ihrer Klasse, um den Validierungsfehler zu halten;
  2. Deklarieren Sie eine Methode, die ausgeführt wird, wenn das Panel effektiv geschlossen wird. Definieren Sie sie so, dass sie den Fehler auf dem aktuellen Fenster präsentiert;
  3. Lassen Sie Ihre Klasse auf NSWindowDidEndSheetNotification auf [self window] hören und führen Sie die oben deklarierte Methode aus, wenn die Benachrichtigung gesendet wird;
  4. Im Panel-Vervollständigungshandler, wenn die Validierung fehlschlägt, weisen Sie den Fehler der oben deklarierten Instanzvariable/-eigenschaft zu.

Indem Sie dies tun, setzt der Vervollständigungshandler nur den Validierungsfehler. Kurz nachdem der Handler aufgerufen wurde, wird das geöffnete Panel geschlossen und die Benachrichtigung wird an Ihr Objekt gesendet, das dann den Validierungsfehler präsentiert, der vom Vervollständigungshandler gesetzt wurde.

Zum Beispiel:

In Ihrer Klassendeklaration fügen Sie hinzu:

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

In Ihrer Klassenimplementierung fügen Sie hinzu:

@synthesize validationError;

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

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

    // Löschen Sie validationError, damit weitere Benachrichtigungen
    // den Fehler nicht anzeigen, es sei denn, ein neuer Fehler wurde festgelegt
    self.validationError = nil;

    // Wenn [self window] andere Dialogfelder anzeigt, möchten Sie nicht,
    // dass diese Methode für sie ausgeführt wird
    [[NSNotificationCenter defaultCenter] removeObserver:self
        name:NSWindowDidEndSheetNotification
        object:[self window]];
}

// Angenommen, ein Aktion löst das Öffnen des Panels aus
- (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) {
            // meine Validierung durchführen
            // oh oh, etwas Schlimmes ist passiert
            self.validationError = error;
        }
    };

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

}

1Wenn Sie dieses Verhalten für falsch halten, erwägen Sie, einen Fehlerbericht bei Apple einzureichen. Ich erinnere mich nicht genau, ob ein Fehler über einem Öffnen/Speichern-Panel präsentiert werden sollte.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X