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

时间:2012-02-05 03:26:20

标签: ios uimenucontroller

使用以下设置

....
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;
}

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

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

4 个答案:

答案 0 :(得分:15)

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

答案 1 :(得分:0)

可以预期与给定菜单项关联的操作将包括应指向所选菜单项的sender参数。然后你可以简单地检查项目的标题,或者像kforkarim建议和子类UIMenuItem那样包括你可以用来识别项目的原则。不幸的是,根据this SO question,sender参数始终为nil。这个问题已经超过一年了,所以事情可能已经发生了变化 - 看看你在这个参数中得到了什么。

或者,看起来您需要为每个菜单项执行不同的操作。当然,你可以设置它,这样你的所有动作都可以调用一个常用的方法,如果它们都做了一些非常相似的事情,那么它们就有意义了。

答案 2 :(得分:0)

如果您继承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(未在旧版本上测试)。

答案 3 :(得分:-1)

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