Я пытаюсь использовать UIMenuController для динамического меню (заголовки, и действия прибывают из сервера). Проблема состоит в том, что я должен использовать UIMenuItems initWithTitle:action: где действие является @selector.
Я могу использовать @selector (отправка:), но затем я не могу различать который из объектов нажатый пользователь. - (пустая) отправка: (идентификатор) отправитель {NSLog ("%", отправитель);} говорит, что это - UIMenuController, и Это не имеет метода, который сказал бы, какой пункт меню был нажат.
Я не могу только записать 100 методов для диспетчеризации каждого возможного селектора, хорошо не будет более затем 10, но тем не менее, это кажется не хорошей идеей.
Я должен создать динамические методы для каждого такого селектора? http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html? Это кажется нечетным также.
Какие-либо лучшие суждения затем это два?
//Этот подход не работает.
- (void)showMenu {
[self becomeFirstResponder];
NSMutableArray *menuItems = [[NSMutableArray alloc] init];
UIMenuItem *item;
for (MLAction *action in self.dataSource.actions) {
item = [[UIMenuItem alloc] initWithTitle:action.title action:@selector(action:)];
[menuItems addObject:item];
[item release];
}
UIMenuController *menuController = [UIMenuController sharedMenuController];
menuController.menuItems = menuItems;
[menuItems release];
[menuController update];
[menuController setMenuVisible:YES animated:YES];
}
- (void)action:(id)sender {
NSLog(@"%@", sender); // gives UIMenuController instead of UIMenuItem
// I can not know which menu item was pressed
}
//Этот подход действительно ужасен.
- (void)showMenu {
[self becomeFirstResponder];
NSMutableArray *menuItems = [[NSMutableArray alloc] initWithCapacity:5];
UIMenuItem *item;
NSInteger i = 0;
for (MLAction *action in self.dataSource.actions) {
item = [[UIMenuItem alloc] initWithTitle:action.text
action:NSSelectorFromString([NSString stringWithFormat:@"action%i:", i++])];
[menuItems addObject:item];
[item release];
}
UIMenuController *menuController = [UIMenuController sharedMenuController];
menuController.menuItems = menuItems;
[menuItems release];
[menuController update];
[menuController setMenuVisible:YES animated:YES];
}
- (void)action:(NSInteger)number {
NSLog(@"%i", number); // gives the index of the action in the menu.
}
// This is a hack, I have to assume that there will never be more then 15 actions
- (void)action0:(id)sender { [self action:0]; }
- (void)action1:(id)sender { [self action:1]; }
- (void)action2:(id)sender { [self action:2]; }
- (void)action3:(id)sender { [self action:3]; }
- (void)action4:(id)sender { [self action:4]; }
- (void)action5:(id)sender { [self action:5]; }
- (void)action6:(id)sender { [self action:6]; }
- (void)action7:(id)sender { [self action:7]; }
- (void)action8:(id)sender { [self action:8]; }
- (void)action9:(id)sender { [self action:8]; }
- (void)action10:(id)sender { [self action:10]; }
- (void)action11:(id)sender { [self action:11]; }
- (void)action12:(id)sender { [self action:12]; }
- (void)action13:(id)sender { [self action:13]; }
- (void)action14:(id)sender { [self action:14]; }
Такой подход будет работать, хотя вам нужно уникальное имя селектора для каждой кнопки и сопоставление этого имени с тем, что вы хотите настроить.
Для имени селектора должна быть выбрана уникальная строка (подойдут UUID или, возможно, очищенная версия заголовка с префиксом). Затем вам понадобится один метод, который разрешает вызов и «псевдоним» его с разными именами селекторов:
- (void)updateMenu:(NSArray *)menuEntries {
Class cls = [self class];
SEL fwd = @selector(forwarder:);
for (MenuEntry *entry in menuEntries) {
SEL sel = [self uniqueActionSelector];
// assuming keys not being retained, otherwise use NSValue:
[self.actionDict addObject:entry.url forKey:sel];
class_addMethod(cls, sel, [cls instanceMethodForSelector:fwd], "v@:@");
// now add menu item with sel as the action
}
}
Теперь сервер пересылки может найти, какой URL-адрес связан с элементом меню:
- (void)forwarder:(UIMenuController *)mc {
NSLog(@"URL for item is: %@", [actionDict objectForKey:_cmd]);
}
Чтобы сгенерировать Вы можете использовать такие селекторы:
- (SEL)uniqueActionSelector {
NSString *unique = ...; // the unique part
NSString *selString = [NSString stringWithFormat:@"menu_%@:", unique];
SEL sel = sel_registerName([selString UTF8String]);
return sel;
}
Если пункты меню не выполняют одно и то же, почему должны совместно использовать действие? Я бы пошел дальше и написал действия, которые определяют желаемое поведение, и связал бы пункты меню с ними.