IOS UIMenuController UIMenuItem,如何确定使用通用选择器方法选择的项目
Posted
技术标签:
【中文标题】IOS UIMenuController UIMenuItem,如何确定使用通用选择器方法选择的项目【英文标题】:IOS UIMenuController UIMenuItem, how to determine item selected with generic selector method 【发布时间】:2012-02-05 03:26:20 【问题描述】:使用以下设置
....
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;
如何确定选择了哪个菜单项。
而且不要说你需要有两种方法......提前谢谢。
【问题讨论】:
所以我想没有办法在 ios 中制作“软”菜单? 【参考方案1】:好的,我已经解决了这个问题。解决方案并不漂亮,更好的选择是“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];
【讨论】:
这是一个支持块的完整实现。 github.com/steipete/PSMenuItem @steipete 你的块实现是天才【参考方案2】:人们会期望与给定菜单项关联的操作将包含一个sender
参数,该参数应指向所选菜单项。然后,您可以简单地检查项目的标题,或者按照 kforkarim 的建议进行操作并将 UIMenuItem 子类化以包含可用于识别项目的属性。不幸的是,根据this SO question,sender 参数始终为零。这个问题已经有一年多了,所以事情可能已经改变了——看看你在那个参数中得到了什么。
另外,您似乎需要对每个菜单项执行不同的操作。当然,您可以设置它,以便您的所有操作都调用一个通用方法,如果它们都执行非常相似的操作,这可能是有意义的。
【讨论】:
尝试制作软菜单。为此,执行不同的操作是不切实际的。参数并不总是 nil,它是一个菜单。我看不出有什么办法可以按照你所说的去做,所以这个问题,谢谢。【参考方案3】:如果您继承 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(未在旧版本上测试)。
【讨论】:
【参考方案4】:ort11,您可能想要创建 myuimenuitem 的属性并设置某种标记。这样,发件人的对象可以通过其标签来识别。然后在 Ibaction 中,您可以设置一个 switch 语句,该语句可以对应于每个 sender.tag 并通过该逻辑工作。我想这是最简单的方法。
【讨论】:
发件人是菜单而不是项目。这就是这个问题的原因。 IOS为什么要这么做?从那以后就没有了。 ord11,无论如何,您正在使用不同的“标题”初始化菜单,那么为什么不能按照 Caleb 的建议检查对象的引用及其标题。由于 sender 只是 id 类型,因此您可以检查特定的 Class 类型,然后对照它检查其“标题”。这样您就可以引用 MyUIMenuItem 类类型。像这样的东西。 if ([sender isKindofClass:[MyUIMenuItem class]]) 然后另一个 if 语句 as if ([sender.title isEqualToString:@"Something2"]) then UIMenuController mmi = (UIMenuController) sender;在这种情况下,您的发件人是 *someAction2。希望这会有所帮助 发件人是菜单,而不是菜单项 ort 最初你的发件人是 menuitem,然后你的铸件是菜单。只需在您投射之前获取您的发件人描述的 nslog,以了解发件人对象的概述 发件人是菜单,不是菜单项以上是关于IOS UIMenuController UIMenuItem,如何确定使用通用选择器方法选择的项目的主要内容,如果未能解决你的问题,请参考以下文章
如何在 iOS 5 中隐藏 UIMenuController
iOS:如何从 UIMenuController 获取选定的 UIMenuItem
iOS 共享 UIMenuController 可能会缓存 UIMenuItem