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