你如何真正从UIMenuController中删除复制

显然,当您添加多个自定义菜单项时,曾经是一种简单的方法来防止“更多…”标签出现在UIMenuController中。 你只需要删除所有的系统菜单项。 这里还有一个解决方法 ,仍然有复印工作。 您只需使用不同的select器实现自定义复制命令,然后重写canPerformAction:withSender:不显示系统副本:

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender { if (action == @selector(copy:)) return NO; else // logic to show or hide other things } 

不幸的是,这种方法不再有效(至less在UIWebView子类中)。 canPerformAction:withSender:对除复制以外的每个系统菜单项都会调用:所以结果是始终显示系统复制菜单项。 这意味着如果您有多个自定义菜单项,则始终隐藏在“更多…”之后

那么,有没有办法真正删除系统的副本项目或一些替代的方法,以防止隐藏在“更多…”后面的菜单项?

更新

这是我重写canPerformAction时获得的输出:withSender:注意,该方法从来没有被调用“copy:”操作:

 cannot perform action cut: with sender <UIMenuController: 0x7227d30>. cannot perform action select: with sender <UIMenuController: 0x7227d30>. cannot perform action selectAll: with sender <UIMenuController: 0x7227d30>. cannot perform action paste: with sender <UIMenuController: 0x7227d30>. cannot perform action delete: with sender <UIMenuController: 0x7227d30>. cannot perform action promptForReplace: with sender <UIMenuController: 0x7227d30>. cannot perform action _showMoreItems: with sender <UIMenuController: 0x7227d30>. cannot perform action _setRtoLTextDirection: with sender <UIMenuController: 0x7227d30>. cannot perform action _setLtoRTextDirection: with sender <UIMenuController: 0x7227d30>. can perform action customCopy: with sender <UIMenuController: 0x7227d30>. can perform action custom1: with sender <UIMenuController: 0x7227d30>. cannot perform action custom2: with sender <UIMenuController: 0x7227d30>. can perform action custom3: with sender <UIMenuController: 0x7227d30>. can perform action custom4: with sender <UIMenuController: 0x7227d30>. cannot perform action cut: with sender <UIMenuController: 0x7227d30>. cannot perform action select: with sender <UIMenuController: 0x7227d30>. cannot perform action selectAll: with sender <UIMenuController: 0x7227d30>. cannot perform action paste: with sender <UIMenuController: 0x7227d30>. cannot perform action delete: with sender <UIMenuController: 0x7227d30>. cannot perform action promptForReplace: with sender <UIMenuController: 0x7227d30>. cannot perform action _showMoreItems: with sender <UIMenuController: 0x7227d30>. cannot perform action _setRtoLTextDirection: with sender <UIMenuController: 0x7227d30>. cannot perform action _setLtoRTextDirection: with sender <UIMenuController: 0x7227d30>. 

你链接到的技术似乎仍然有效。 我用这些方法实现了一个UIWebView子类,只有A和B项出现。

 + (void)initialize { UIMenuItem *itemA = [[UIMenuItem alloc] initWithTitle:@"A" action:@selector(a:)]; UIMenuItem *itemB = [[UIMenuItem alloc] initWithTitle:@"B" action:@selector(b:)]; [[UIMenuController sharedMenuController] setMenuItems:[NSArray arrayWithObjects:itemA, itemB, nil]]; [itemA release]; [itemB release]; } - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { BOOL can = [super canPerformAction:action withSender:sender]; if (action == @selector(a:) || action == @selector(b:)) { can = YES; } if (action == @selector(copy:)) { can = NO; } NSLog(@"%@ perform action %@ with sender %@.", can ? @"can" : @"cannot", NSStringFromSelector(action), sender); return can; } 

对于ios> = 5.1 canPerformAction:(SEL)行动withSender:(id)发件人不再工作。

如果你确定只是禁用粘贴动作,这里是一个方法:

添加UITextFieldDelegate到你的视图控制器和实现这样的方法

 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{ if(textField == txtEmailRe) return ((string.length) > 1 ? NO : YES); } 

这意味着如果用户为每个动作input了多个字符(这意味着用户可能正在粘贴某些东西),请不要在文本框中接受它。

强制用户input电子邮件和电子邮件等文本字段是一个很好的做法

lemnar的回答是正确的。 实现UIWebView的子类很好。 这个例子对于UITextView是可以的。 对于UIWebView,创build一个自定义的子类如下:

 // // MyUIWebView.h // #import <UIKit/UIKit.h> @interface MyUIWebView : UIWebView @end 

和:

 // // MyUIWebView.m // #import "MyUIWebView.h" @implementation MyUIWebView -(BOOL)canPerformAction:(SEL)action withSender:(id)sender { if (action == @selector(copy:)) return NO; else // logic to show or hide other things } @end 

然后,而不是实例化UIWebView,使用MyUIWebView。

更新

如果想禁用“复制”,但留下“定义”(和“翻译”),这是有用的,这是如何做到这一点; 用canPerformAction:withSenderreplacecanPerformAction:withSender

 -(BOOL)canPerformAction:(SEL)action withSender:(id)sender { if (action == @selector(defineSelection:)) { return YES; } else if (action == @selector(translateSelection:)) { return YES; } else if (action == @selector(copy:)) { return NO; } return [super canPerformAction:action withSender:sender]; } 

这是一个适用于我的iOS5.x解决scheme。 这是由乔什Garnham,build议创build一个UIWebBrowserView类别来捕获副本:,粘贴:,定义:select器。

http://ios-blog.co.uk/iphone-development-tutorials/rich-text-editing-highlighting-and-uimenucontroller-part-3/

 @implementation UIWebBrowserView (UIWebBrowserView_Additions) - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { return NO; } @end 

请注意FTR:在这个优秀的网页上有一个轻微的错字。 这正是你如何做的。 苹果将100%拒绝这一点。 做一个类别

在这里输入图像说明

(您必须input“UIWebBrowserView”,因为Xcode不会显示私有类。).h和.m文件的全文:

 // .h file... #import "UIWebBrowserView+Tricky.h" @interface UIWebBrowserView : UIView @end @interface UIWebBrowserView(Tricky) @end // .m file... #import "UIWebBrowserView+Tricky.h" @implementation UIWebBrowserView (Tricky) -(BOOL)canPerformAction:(SEL)action withSender:(id)sender { NSLog(@"don't let Apple see this"); return NO; } @end 

为了logging,“单击”仍然会带来烦人的拼写检查build议! 但是否则它完全去除了双击上下文菜单,它被苹果100%拒绝。

我很抱歉我的英语。 但是有一个想法。

我认为方法canPerformAction被多次调用,但你只需处理一次。 在这种情况下,我认为可能有另一个UI控件调用它。 例如,UIWebView中的UITextView控件。

我想你可能会通过故事板生成UI。 故事板中并不是每个控件都有自己的类。 您可以为响应控件定义一个类并重写其canPerformAction方法。

您可以绘制自己的菜单,而不是使用UIMenuController。 这样,您可以同时显示多个项目,而无需使用其他项目。