IOS UIMenuController UIMenuItem,如何确定用通用选择器方法选择的项目

通过以下设置

.... MyUIMenuItem *someAction = [[MyUIMenuItem alloc]initWithTitle : @"Something" action : @selector(menuItemSelected:)]; MyUIMenuItem *someAction2 = [[MyUIMenuItem alloc]initWithTitle : @"Something2" action : @selector(menuItemSelected:)]; .... - (IBAction) menuItemSelected : (id) sender { UIMenuController *mmi = (UIMenuController*) sender; } 

如何确定选择了哪个菜单项。

并且不要说你需要有两种方法……提前谢谢。

好的,我已经解决了这个问题。 解决方案并不漂亮,更好的选择是“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; 

现在,您的class级抓住按钮点击消息需要一些补充。 (在我的例子中,类是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]; } } 

可以预期与给定菜单项相关联的动作将包括应指向所选菜单项的sender参数。 然后你可以简单地检查项目的标题,或者像kforkarim建议和子类UIMenuItem那样包含一个可以用来标识项目的标准。 不幸的是,根据这个SO问题 ,sender参数总是为零。 这个问题已经过了一年多了,所以事情可能已经改变了 – 看看你在那个参数中得到了什么。

或者,看起来您需要为每个菜单项执行不同的操作。 当然,您可以对其进行设置,以便您的所有操作都可以调用常用方法,如果它们都执行非常相似的操作,那么这些操作可能是有意义的。

事实certificate,如果您将UIApplication子类化并重新实现-sendAction:to:from:forEvent: :,则可以获取表示UIMenuItem的UIButton对象(实际上是UICalloutBarButton)。 虽然只有-flash选择器通过UIApplication,但它已经足够了。

 @interface MyApplication : UIApplication @end @implementation MyApplication - (BOOL)sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent *)event { // target == sender condition is just an additional one if (action == @selector(flash) && target == sender && [target isKindOfClass:NSClassFromString(@"UICalloutBarButton")]) { NSLog(@"pressed menu item title: %@", [(UIButton *)target titleLabel].text); } return [super sendAction:action to:target from:sender forEvent:event]; } @end 

您可以在例如属性中保存target (或您需要的任何数据),然后从UIMenuItem的操作中访问它。

要使UIApplication子类起作用,必须将其名称作为第三个参数传递给UIApplicationMain()

 int main(int argc, char *argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, NSStringFromClass([MyApplication class]), NSStringFromClass([YOUR_APP_DELEGATE class])); } } 

此解决方案适用于发布日期的iOS 5.x-7.0(未在旧版本上测试)。

ort11,您可能想要创建myuimenuitem的属性并设置某种Tag。 Thay方式发送者的对象可以通过其标记来识别。 在Ibaction中,您可以设置一个switch语句,该语句可以对应每个sender.tag并完成该逻辑。 我想那是最简单的方法。