动态 NSTooltips:影响工具提示的事件键修饰符

Dynamic NSTooltips: Event Key Modifier(s) Affecting Tooltips

是否有工具提示的通知机制,然后可以使用键修饰符使它们动态化?我不知道有哪一个因此采用这条路径来捕获正在创建的工具提示视图并尝试在发生关键事件时触发重绘。

我监控键修饰符(在我的应用委托中);在这里关注 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 拦截到 post 通知(因此当值更改时发送通知!):

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 名称来执行此操作)看起来很有希望并找到了一个 - 通过监视所有通知等等我 post 对它感兴趣的视图控制器是 tableView 的委托。视图控制器正在观察 "CustomToolTipView" 并记住对象发送 - tooltipView;这是创建的新工具提示视图。

但没有任何反应 - shiftKeyDown(),重绘视图。

我怀疑它不会在当前事件循环中更新,但我确实看到了调试输出。

根据 Willeke's 建议,我将 tableView 迁移为基于单元格的,为工具提示添加了一个 get 属性 并让相关对象的 init() 例程注册通知以更改 shift 键。这导致更少的代码。一个 win-win :-)