Home > Net >  KVO on NSStatusItem.isVisible fires twice
KVO on NSStatusItem.isVisible fires twice

Time:11-05

I'm trying to use key value observation to determine when an NSStatusItem is dragged out of the menu bar by the user with the removalAllowed behavior. This is supported according to the docs:

Status items with this behavior allow interactive removal from the menu bar. Upon removal, the item’s isVisible property changes to false. This change is observable using key-value observation.

However, the callback function seems to fire twice whenever the isVisible property is changed. Here's a minimal example (assume statusItem and observer are variables that are retained for the lifetime of the app, e.g. on AppDelegate).

statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)
statusItem.button!.image = NSImage(named: NSImage.addTemplateName)
statusItem.behavior = .removalAllowed

observer = statusItem.observe(\.isVisible, options: [.old, .new]) { object, change in
    print("oldValue: \(change.oldValue!) newValue: \(change.newValue!)")
}

If you drag the icon out of the menu bar, it will print the following:

oldValue: false newValue: true
oldValue: false newValue: true

I've looked through every property on the change object and as far as I can tell, they're all identical, so there'd be no easy way to discard the duplicate event. I've also messed with the prior option, which doesn't seem to help either.

CodePudding user response:

A smart way to get rid of duplicates is to replace the KVO observer with a Combine publisher.

import Combine

var cancellable : AnyCancellable?

cancellable = statusItem.publisher(for: \.isVisible)
    .removeDuplicates()
    .sink { value in
        print(value)
    }

If you are interested in the old value you could add the Scan operator

  • Related