2017-02-26 75 views
2

我有一個NSToolbarItem NSButton作爲其視圖和NSMenuItem在主菜單中。兩者都有相同的行爲,發送給第一響應者,而不是發送給特定的目標。該方法最終在NSSplitViewController的子類中實現,該子類位於窗口內容視圖的視圖層次結構中的某處。我想驗證這兩個項目,但是要讓該特定的分割視圖控制器負責驗證,因爲它依賴於該控制器本地的一些條件。NSToolbarItem驗證在相關的控制器

我在該分屏控制器中覆蓋了validateToolbarItem(_:)validateMenuItem(_:)。對於菜單項,這是按預期工作的。該方法被調用並且驗證發生。然而,從未調用過validateToolbarItem(_:)

根據Apple’s documentation,NSToolbar不會將validateToolbarItem(_:)發送到基於視圖的工具欄項目。爲了測試這個,我用工具欄項目替換了工具欄項目,並且它按預期工作。

基於此,我遇到了幾個解決方案,但他們不是我想要的。

  • 子類NSToolbarItem並覆蓋validate()。然而,我沒有給出任何指導,我最終得到的控制器的validateToolbarItem(_:)來電。

  • 子類NSToolbar並覆蓋validateVisibleToolbarItems(),然後發送消息給第一響應者。在這裏,我遇到了這個問題,我無法發送消息到分割視圖控制器,因爲它位於工具欄的響應者鏈之外。

  • 如上所述的NSToolbar子類,但在響應器鏈內的控制器中實現了validateToolbarItem(_:),如NSWindowController。這會起作用,但是我必須添加額外的代碼來處理菜單項不需要的內容。

是否有一個優雅的解決方案,它的工作原理與圖像工具欄項目和菜單項一樣?

回答

2

我在按鈕的NSToolbarItem子類中編寫了下面的代碼。使用此toolbarItem子類,可以使用普通的validateUserInterfaceItem()validateToolbarItem()來驗證包含NSControl的工具欄項目。

override func validate() { 

    // validate content view 
    if 
     let control = self.view as? NSControl, 
     let action = self.action, 
     let validator = NSApp.target(forAction: action, to: self.target, from: self) as AnyObject? 
    { 
     switch validator { 
     case let validator as NSUserInterfaceValidations: 
      control.isEnabled = validator.validateUserInterfaceItem(self) 
     default: 
      control.isEnabled = validator.validateToolbarItem(self) 
     } 

    } else { 
     super.validate() 
    } 
} 
+0

神奇,只是我尋找的優雅的解決方案。非常感謝! – Eitot

+0

美麗!感謝分享這個。你介意解釋兩件事:1)爲什麼這甚至是需要的 - 爲什麼可可不這樣做?和b)我多久應該期待這個被稱爲?在我快速實現你的代碼時,它似乎被稱爲非常不可預測的,而且經常。 –

+0

@ jeff-h 1)NSToolbarItem的內部視圖可以不僅僅是一個NSControl。所以Cocoa不知道它是什麼,因此如何驗證它。 2)這是一個活動組合和一個計時器。您可以在引用中看到驗證時間的詳細信息:https://developer.apple.com/reference/appkit/nstoolbar/1516947-validatevisibleitems – 1024jp