【问题标题】:Dynamic UIMenuItems with @selector and dynamic methods带有 @selector 和动态方法的动态 UIMenuItems
【发布时间】:2010-07-14 18:21:48
【问题描述】:

我正在尝试将 UIMenuController 用于动态菜单(标题和操作来自服务器)。问题是我必须使用 UIMenuItems initWithTitle:action: 其中 action 是 @selector。

我可以使用@selector(dispatch:) 但我无法区分用户按下了哪些项目。 - (void)dispatch:(id)sender { NSLog(@"%@", sender); } 说它是一个 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]; }

【问题讨论】:

    标签: iphone objective-c uimenucontroller


    【解决方案1】:

    这种方法可行,但您需要为每个按钮设置一个唯一的选择器名称,并将该名称映射到您想要定位的任何内容。
    对于选择器名称,必须选择一个唯一的字符串(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;
    }
    

    【讨论】:

    • _cmd 从何而来,又是什么?
    • @jen:调用实现函数的选择器的关键字。尝试记录NSStringFromSelector(_cmd)
    【解决方案2】:

    除非菜单项做同样的事情,为什么应该他们共享一个动作?我会继续编写操作来指定您想要的行为并将菜单项链接到这些操作。

    【讨论】:

    • 问题是我不知道编译时会有哪些操作,因为这些操作将来自服务器,它始终是菜单的标题和应该是的 http-url当用户点击它时调用。我会用一些代码更新问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-02
    • 1970-01-01
    相关资源
    最近更新 更多