3

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のドキュメントによると、完了ハンドラーは「ユーザーがパネルを閉じた後に」呼び出されることになっています。しかし、私の場合は、パネルが閉じたときではなく、「OK/キャンセル」ボタンを押すとすぐに呼び出されます。これにより、パネルが閉じた後ではなく、開いているパネルの上でエラーアラートが開きます。それでも動作しますが、Macのようなものではありません。

ユーザーが[OK]をクリックし、開いているパネルシートを折りたたんでから、アラートシートを表示することをお勧めします。

遅延セレクターを使用してアラートを表示できると思いますが、それはハックのようです。

4

1 に答える 1

5

パネルが効果的に閉じられる前にパネル完了ハンドラーが呼び出されるため、1NSWindowDidEndSheetNotificationつの解決策はモーダルウィンドウで観察することです。

  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にバグレポートを提出することを検討してください。開いた/保存したパネルにエラーを表示する必要があるかどうかはよく覚えていません。

于 2011-10-15T07:26:28.853 に答える