UIMenu — how to perform action on open

Evgeny Cherpak
2 min readSep 10, 2020

Apple added ability to assign menus to buttons in iOS 14, but unfortunately UIMenu is poor mans replacement of NSMenu. There are no delegates to it — you assign it, and its triggered without any chance for you to intervene. And sometimes you do need to…

I have this view controller with a tip view that I want to close automatically when someone taps the button. It only make sense, right?

The button has UIMenu associated with it, which includes share action along with some other actions.

Normally you would create UIBarButtonItem with one of the default inits that accept menu, but then as I said, you have no control over what to do when its presented. But… thanks to David Duncan tip, I was able to create somewhat convoluted but working solution to this.

@available(iOS 14.0, *)protocol UIMenuButtonDelegate: class {func didTriggerMenuAction(button: UIMenuButton)}@available(iOS 14.0, *)class UIMenuButton: UIButton {weak var delegate: UIMenuButtonDelegate?convenience init(menu: UIMenu) {self.init(type: .custom)self.showsMenuAsPrimaryAction = trueself.menu = menu}override func sendActions(for controlEvents: UIControl.Event) {super.sendActions(for: controlEvents)if controlEvents.contains(.menuActionTriggered) {delegate?.didTriggerMenuAction(button: self)}}}

Which you can use like this:

let button = UIMenuButton(menu: UIMenu(title: "", children: menuItems))button.setImage(UIImage(named: "more"), for: .normal)button.delegate = selflet barButton = UIBarButtonItem(customView: button)

--

--

Evgeny Cherpak

Indie iOS/Mac developer, focusing mostly on Remote Control app for Mac. Libertarian. "I am the master of my fate, I am the captain of my soul."