Существует ли механизм уведомлений для всплывающих подсказок, поэтому можно использовать ключевые модификаторы, чтобы сделать их динамичными? Я не знаю ни одного, поэтому пошел по этому пути, чтобы захватить создаваемое представление всплывающей подсказки и пытаться вызвать перерисовку, когда происходит ключевое событие.
Я отслеживаю ключевые модификаторы (в моем делегате приложения); сосредоточив внимание на SHIFT здесь, но любой ключевой модификатор подойдет:
var localKeyDownMonitor : Any? = nil
var globalKeyDownMonitor : Any? = nil
var shiftKeyDown : Bool = false {
didSet {
let notif = Notification(name: Notification.Name(rawValue: "shiftKeyDown"),
object: NSNumber(booleanLiteral: shiftKeyDown));
NotificationCenter.default.post(notif)
}
}
, который установит процесс запуска приложения ...
// Local/Global Monitor
_ /*accessEnabled*/ = AXIsProcessTrustedWithOptions([kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String: true] as CFDictionary)
globalKeyDownMonitor = NSEvent.addGlobalMonitorForEvents(matching: NSEventMask.flagsChanged) { (event) -> Void in
_ = self.keyDownMonitor(event: event)
}
localKeyDownMonitor = NSEvent.addLocalMonitorForEvents(matching: NSEventMask.flagsChanged) { (event) -> NSEvent? in
return self.keyDownMonitor(event: event) ? nil : event
}
, а затем перехватить отправку уведомлений через делегат приложения didSet выше (поэтому при изменении значения отправляется уведомление!):
func keyDownMonitor(event: NSEvent) -> Bool {
switch event.modifierFlags.intersection(.deviceIndependentFlagsMask) {
case [.shift]:
self.shiftKeyDown = true
return true
default:
// Only clear when true
if shiftKeyDown { self.shiftKeyDown = false }
return false
}
}
Для одноэлементных привязок всплывающей подсказки это может быть динамическим, если в уведомлении сообщается (KVO о некотором ключе), я бы хотел, чтобы процедура делегата представления действовала на этом:
func tableView(_ tableView: NSTableView, toolTipFor cell: NSCell, rect: NSRectPointer, tableColumn: NSTableColumn?, row: Int, mouseLocation: NSPoint) -> String {
if tableView == playlistTableView
{
let play = (playlistArrayController.arrangedObjects as! [PlayList])[row]
if shiftKeyDown {
return String(format: "%ld play(s)", play.plays)
}
else
{
return String(format: "%ld item(s)", play.list.count)
}
}
...
Так что я бы хотел, чтобы мой обработчик уведомлений делал что-то вроде
internal func shiftKeyDown(_ note: Notification) {
let keyPaths = ["cornerImage","cornerTooltip","<table-view>.<column-view>"]
for keyPath in (keyPaths)
{
self.willChangeValue(forKey: keyPath)
}
if subview.className == "NSCustomToolTipDrawView" {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "CustomToolTipView"), object: subview)
}
for keyPath in (keyPaths)
{
self.didChangeValue(forKey: keyPath)
}
}
где я хотел бы заставить всплывающую подсказку перерисовываться, но ничего не происходит.
То, что я сделал, чтобы получить представление всплывающей подсказки, - это просмотр любого уведомления (используйте для этого имя nil), которое выглядело многообещающим и нашло одно - путем мониторинга всех уведомлений, поэтому я публикую в нем заинтересованные контроллер представления, который является делегатом tableView. Контроллер представления наблюдает за «CustomToolTipView» и запоминает объект send - tooltipView; это новый вид всплывающей подсказки.
Но ничего не происходит - shiftKeyDown (), чтобы перерисовать представление.
Я подозреваю, что он не будет обновляться в текущем цикле событий, но я вижу выходные данные отладки.