2011-10-15 63 views
3

我有一個NSOpenPanel,我想在用戶點擊確定之後對選擇進行一些驗證。我的代碼很簡單:在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]是一個應用程序模式窗口。面板以表格形式打開。到現在爲止還挺好。

Apple的文檔說完成處理程序應該被稱爲「在用戶關閉面板後」。但在我的情況下,它會在「確定/取消」按鈕按下時立即調用,而不是面板關閉。這樣做的效果是錯誤警報在打開面板上方打開,而不是在面板關閉後打開。它仍然有效,但它不像Mac。

我更喜歡用戶點擊確定,打開面板表單摺疊起來,然後然後出現警報單。

我想我可以使用延遲選擇器來顯示警報,但這似乎是一個黑客。

回答

5

由於面板已經有效關閉前面板完成處理程序被調用,一種解決方案是你的模態窗口觀察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]; 

} 

如果您認爲此行爲是錯誤的,請考慮filing a bug report with Apple。我不記得是否應該在打開/保存面板上顯示錯誤。