Лучший практический способ проверки элементов NSTouchBar
В AppKit элементы меню и панели инструментов имеют validateMenuItem(_:)
а также validateToolbarItem(_:)
соответственно. Однако, благодаря новым элементам сенсорной панели, нет такого удобного метода для проверки соответствующих элементов в нужный момент.
Теперь я проверяю элементы сенсорной панели каждый раз, когда я изменяю связанные значения и вызываю метод проверки в didSet
(см. следующий пример кода). Но я чувствую, что это не очень хороший способ, потому что связанные значения должны знать, что в зависимости от него есть элемент сенсорной панели.
var foo: Foo? {
didSet {
if #available(macOS 10.12.1, *), NSClassFromString("NSTouchBar") != nil {
self.validateTouchBarItem(identifier: .foo)
}
}
}
@available(macOS 10.12.1, *)
func validateTouchBarItem(identifier: NSTouchBarItemIdentifier) {
guard
let item = self.touchBar?.item(forIdentifier: identifier),
let button = item.view as? NSButton
else { return }
switch identifier {
case NSTouchBarItemIdentifier.foo:
button.isEnabled = (self.foo != nil)
default: break
}
}
Другой способ, которым я пользуюсь - это привязка к Какао и KVO, однако, это не всегда хорошо работает.
Итак, мне любопытно, есть ли какой-либо рекомендуемый или стандартный метод проверки элементов сенсорной панели, особенно содержащий NSButton и NSSegmentedControl. Я хочу изменить не только наличие предметов, но иногда и их изображения или цвета в зависимости от ситуации. Как вы проверяете элементы сенсорной панели?
1 ответ
Я усовершенствовал свою систему проверки сенсорной панели и сделал следующий протокол и расширения.
@available(macOS 10.12.1, *)
protocol TouchBarItemValidations: class {
func validateTouchBarItem(_ item: NSTouchBarItem) -> Bool
}
@available(macOS 10.12.1, *)
extension NSTouchBarProvider {
func validateTouchBarItems() {
guard NSClassFromString("NSTouchBar") != nil else { return } // run-time check
guard let touchBar = self.touchBar else { return }
// validate currently visible touch bar items
for identifier in touchBar.itemIdentifiers {
guard let item = touchBar.item(forIdentifier: identifier) as? NSCustomTouchBarItem else { continue }
item.validate()
}
}
}
@available(macOS 10.12.1, *)
extension NSCustomTouchBarItem: NSValidatedUserInterfaceItem {
func validate() {
// validate content control
if let control = self.control,
let action = control.action,
let validator = NSApp.target(forAction: action, to: control.target, from: self)
{
if let validator = validator as? TouchBarItemValidations {
control.isEnabled = validator.validateTouchBarItem(self)
} else if let validator = validator as? NSUserInterfaceValidations {
control.isEnabled = (validator as AnyObject).validateUserInterfaceItem(self)
}
}
}
// MARK: Validated User Interface Item Protocol
public var action: Selector? {
return self.control?.action
}
public var tag: Int {
return self.control?.tag ?? 0
}
// MARK: Private Methods
private var control: NSControl? {
return self.view as? NSControl
}
}
@available(macOS 10.12.1, *)
extension AppDelegate {
func applicationDidUpdate(_ notification: Notification) {
// validate touch bar items
if #available(macOS 10.12.1, *) {
if let window = NSApp.mainWindow {
for responder in sequence(first: window.firstResponder, next: { $0.nextResponder }) {
responder.validateTouchBarItems()
}
}
}
}
}
Вы должны изменить AppDelegate's applicationDidUpdate(:_)
если у вас уже есть, но кроме этого, ничего сложного добавить. Теперь вы можете использовать validateTouchBarItem(_:)
или нормально validateUserInterfaceItem(_:)
проверить свои собственные элементы сенсорной панели!
Я полагаю, это хорошо работает, по крайней мере, для моих требований.