你如何真正从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:withSender
replacecanPerformAction: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器。
@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。 这样,您可以同时显示多个项目,而无需使用其他项目。