iOS Uimenucontroller Uimenuitem, How to Determine Item Selected with Generic Selector Method

IOS UIMenuController UIMenuItem, how to determine item selected with generic selector method

Okay, I've solved this one. The solution isn't pretty, and the better option is "Apple fixes the problem", but this at least works.

First of all, prefix your UIMenuItem action selectors with "magic_". And don't make corresponding methods. (If you can do that, then you don't need this solution anyway).

I'm building my UIMenuItems thus:

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 the button tap messages needs a few additions. (In my case the class is a subclass of UITextField. Yours might be something else.)

First up, the method that we've all been wanting to have but that didn't exist:

- (void)tappedMenuItem:(NSString *)buttonText {
NSLog(@"They tapped '%@'", buttonText);
}

Then the methods that make it possible:

- (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];
}
}

iOS: How to get the selected UIMenuItem from UIMenuController

Okay, I've solved this one. It involves messing with [NSObject forwardInvocation:] and is a bit dirty, but the resulting code is quite minimal. Answered over here: https://stackoverflow.com/a/9874092/790036

How to display more than one line in UIMenuItem?

You would need to change some internal property of the UIMenuItem, but unfortunately Apple does not provide a way to do it.

So, as for today, there's not way to change the display of a UIMenuItem.

Why is the sender of an UIMenuItem action always nil?

I also came across that once. Looks like a bug to me.

Get Tag value from custom class

If I'm not wrong, a KXMenuItem is not a subclass of UIView, which means that there is no tag property available for free.

You could, however, either use different selectors for different menu items, or check for the title of the sender and base your decision on what it matches. For example:

- (void) pushMenuItem:(id)sender
{
KXMenuItem *selected = (KXMenuItem*)sender;
if ( [selected.title isEqualToString:@"Share this on Facebook"] ){
//share on facebook
}
else //And so on
}

Get Tag value from custom class

If I'm not wrong, a KXMenuItem is not a subclass of UIView, which means that there is no tag property available for free.

You could, however, either use different selectors for different menu items, or check for the title of the sender and base your decision on what it matches. For example:

- (void) pushMenuItem:(id)sender
{
KXMenuItem *selected = (KXMenuItem*)sender;
if ( [selected.title isEqualToString:@"Share this on Facebook"] ){
//share on facebook
}
else //And so on
}


Related Topics



Leave a reply



Submit