Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine when a UIMenuController is dismissed?

Is there a way to determine when a UIMenuController has been dismissed? I have a (non-editable) text area I'm highlighting when the menu is brought up, and I'd like to un-highlight it when they either select an item (easy) or cancel (not possible?)

like image 735
Ben Gottlieb Avatar asked Sep 07 '10 03:09

Ben Gottlieb


3 Answers

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];
like image 131
Markus Müller-Simhofer Avatar answered Oct 28 '22 14:10

Markus Müller-Simhofer


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.

like image 36
William Denniss Avatar answered Oct 28 '22 14:10

William Denniss


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)
like image 22
eduardo Avatar answered Oct 28 '22 12:10

eduardo