Хорошо, я решил это. Решение не изящное, и лучший вариант - «Apple решает проблему», но это, по крайней мере, работает.
Прежде всего, префикс ваших UIMenuItem селекторов действий с " magic_ ". И не делайте соответствующие методы. (Если вы можете сделать это, то вам все равно не нужно это решение).
Я создаю свои UIMenuItems таким образом:
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;
Теперь вашему классу, который ловит сообщения о нажатиях кнопок, нужно несколько дополнений. (В моем случае класс является подклассом UITextField . Ваш может быть чем-то другим.)
Прежде всего, метод, который мы все хотели иметь, но которого не было:
- (void)tappedMenuItem:(NSString *)buttonText {
NSLog(@"They tapped '%@'", buttonText);
}
Тогда методы, которые делают это возможным:
- (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];
}
}