4
votes

I have successfully been able to add a custom UIMenuItem to the Copy & Paste menu in my iPhone app, and even subclassed UITextView to get rid of the standard menu items. However, what I need to do is to somehow capture the fact that the menu is going to be displayed before it actually happens, and add the word at the insertion point into the menu.

For example, if the text in the UITextView is "This is a test.", and the person touched the word "is", it would add that word as a UIMenuItem to the UIMenuController.

It is important that the menu show the word only directly after it has been touched. The next invocation of the menu would show the next word touched, etc. Touching the word in the menu would then show more detail. I already have code that finds the word touched based on selectedRange. All I need to do is to add that word as a UIMenuItem before the menu displays. Another less elegant solution might be to allow the person to touch a static menu item that then adds and redisplays the menu, with different options, based on the word touched.

I am hoping that there is a way to intercept the UIMenuController, possibly by subclassing it, so that I can get to the insertion point before the balloon displays, but still able to effect a change to it, by changing the menu item list.

Is there a way to do this? Can anybody show me a code snippet or point me to some documentation that might help me? Thanks.

My only other solution is to somehow create my own balloon and somehow disable the Copy & Paste menu. I would rather not have to try that.

2

2 Answers

5
votes

At startup somewhere:

UIMenuItem *testMenuItem = [[UIMenuItem alloc] initWithTitle:@"Test" action:@selector(test:)];
[UIMenuController sharedMenuController].menuItems = [NSArray arrayWithObject:testMenuItem];
[testMenuItem release];

And in your UITextView or UITextField subclass:

@implementation MyTextView
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    if (action == @selector(test:)) {
        // Return YES only if it's possible to perform the action at this time
        return YES;
    }
    return [super canPerformAction:action withSender:sender];
}
- (void)test:(id)sender {
    // Perform the action here
}
@end
0
votes

If the question is still relevant then you could use the UIMenuControllerWillShowMenuNotification or the UIMenuControllerDidShowMenuNotification notification.
See the documentation here.

Code sample:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willShowMenu:) name:UIMenuControllerWillShowMenuNotification object:nil];