Determine when a UIMenuController is dismissed?

Building on @Markus Müller's suggestion, here's a pattern you can copy:

- (BOOL)becomeFirstResponder
{
    // starts listening for UIMenuControllerDidHideMenuNotification & triggers resignFirstResponder if received
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resignFirstResponder) name:UIMenuControllerDidHideMenuNotification object:nil];
    return [super becomeFirstResponder];
}

- (BOOL)resignFirstResponder
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIMenuControllerDidHideMenuNotification object:nil];

    // your custom cleanup code here (e.g. deselection)

    return [super resignFirstResponder];
}

In my case I have hundreds of selectable objects, so I didn't want them all observing this notification all the time! What this pattern does start observing when it gains firstResponder, triggers resignFirstResponder when the menu is dismissed, and ends observing in the same.

In my my case (as in the OP's), as the item is uneditable it is desirable for me to call resignFirstResponder when the menu is dismissed. This way, resignFirstResponder gets called if whether they select one of the menu options, or not, so the cleanup code will always fire.


Swift 3 & 4

NotificationCenter.default.addObserver(
   self,
   selector: #selector(self.didHideEditMenu),
   name: NSNotification.Name.UIMenuControllerDidHideMenu,
   object: nil)

NotificationCenter.default.addObserver(
   self,
   selector: #selector(self.willHideEditMenu),
   name: NSNotification.Name.UIMenuControllerWillHideMenu,
   object: nil)

On state changes UIMenuController posts notifications to the default NSNotification center. You can subscribe to them to get notified when the system hides the menu:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willHideEditMenu:) name:UIMenuControllerWillHideMenuNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didHideEditMenu:) name:UIMenuControllerDidHideMenuNotification object:nil];