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并完成该逻辑。 我想那是最简单的方法。