I started down this rabbit hole because a SwiftUI button, designated to pop up a menu, with a .buttonStyle(BorderlessButtonStyle()) style wasn't behaving correctly when switching from a light to a dark mode.
Frustrated, I decided to just make my own button. I noticed the SwiftUI button would sort of toggle when popping up the menu and so I want this behaviour for my button as well. Therefore, I need to find out when an NSMenu is closed.
I've tried the answer suggested here ⤵︎
class NSMenuDelegateModified: NSObject, NSMenuDelegate, ObservableObject {
var menu: NSMenu
@Published var isVisible: Bool?
internal init(menu: NSMenu) {
self.menu = menu
super.init()
self.menu.delegate = self
}
func menuDidClose(_ menu: NSMenu) {
isVisible = false
}
func menuWillOpen(_ menu: NSMenu) {
isVisible = true
}
}
Now this will tell me if the menu is visible from within the class, but when I try to print out .isVisible on an instantiated object of the class, it only returns false.
Is there a way to figure this out?
So I figured out why I can't get
trueout of.isVisibleoutside of the class! It's because I usemenu.popUp(...)to open up my menu.It turns out that this function pauses execution for some parts of the app or perhaps the whole main thread (I'm really not sure) until it can return a state ⤵︎
You can see more details on Apple's documentation.
Solution
With this in mind, it made everything a lot easier! To toggle the button I could simply change the color after calling
menu.popUp(...).This would mean that when the menu was popped up, the color wouldn't change again until a state was returned from the function and execution was resumed!
Updated Answer
It looks like I messed up the functionality and it was more complicated than I anticipated. Here is what I ended up with below ⤵︎
This solution is pretty specific to my needs so I hope what is said here still helps someone. Hopefully, someone can come up with a better answer than this.
Old Answer (This is incorrect and doesn't work as intended)