Ok, I solved it. The solution is not very pretty, and the best option is βApple fixes the problem,β but at least it works.
First of all, the UIMenuItem action selector prefix with the magic _ parameter. And do not do the appropriate methods. (If you can do this, then you still do not need this solution).
I build my UIMenuItems in this way:
NSArray *buttons = [NSArray arrayWithObjects:@"some", @"random", @"stuff", nil]; NSMutableArray *menuItems = [NSMutableArray array]; for (NSString *buttonText in buttons) { NSString *sel = [NSString stringWithFormat:@"magic_%@", buttonText]; [menuItems addObject:[[UIMenuItem alloc] initWithTitle:buttonText action:NSSelectorFromString(sel)]]; } [UIMenuController sharedMenuController].menuItems = menuItems;
Now your class that catches button click messages needs a few additions. (In my case, the class is a subclass of UITextField . Maybe it could be something else.)
First, the method that we all wanted to have, but which was not:
- (void)tappedMenuItem:(NSString *)buttonText { NSLog(@"They tapped '%@'", buttonText); }
Then methods that allow you to:
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender { NSString *sel = NSStringFromSelector(action); NSRange match = [sel rangeOfString:@"magic_"]; if (match.location == 0) { return YES; } return NO; } - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel { if ([super methodSignatureForSelector:sel]) { return [super methodSignatureForSelector:sel]; } return [super methodSignatureForSelector:@selector(tappedMenuItem:)]; } - (void)forwardInvocation:(NSInvocation *)invocation { NSString *sel = NSStringFromSelector([invocation selector]); NSRange match = [sel rangeOfString:@"magic_"]; if (match.location == 0) { [self tappedMenuItem:[sel substringFromIndex:6]]; } else { [super forwardInvocation:invocation]; } }
sobri source share