Ios 如何真正从UIMenuController中删除副本

Ios 如何真正从UIMenuController中删除副本,ios,cocoa-touch,uimenucontroller,Ios,Cocoa Touch,Uimenucontroller,显然,当您添加多个自定义菜单项时,有一种方法可以防止“更多…”标签出现在UIMenuController中。您只需删除所有系统菜单项。甚至还有一个理由,那就是仍然有复印工作。您只需使用不同的选择器实现自定义复制命令,然后覆盖canPerformAction:withSender:以不显示系统副本: -(BOOL)canPerformAction:(SEL)action withSender:(id)sender { if (action == @selector(copy:))

显然,当您添加多个自定义菜单项时,有一种方法可以防止“更多…”标签出现在UIMenuController中。您只需删除所有系统菜单项。甚至还有一个理由,那就是仍然有复印工作。您只需使用不同的选择器实现自定义复制命令,然后覆盖canPerformAction:withSender:以不显示系统副本:

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender 
{
    if (action == @selector(copy:))
       return NO;
    else
       // logic to show or hide other things
}
不幸的是,此方法不再有效(至少在UIWebView子类中是如此)。canPerformAction:withSender:为除copy:之外的每个系统菜单项调用,因此结果是始终显示system copy菜单项。这意味着,如果您有多个自定义菜单项,它们总是隐藏在“更多…”后面

那么,有没有一种方法可以真正删除系统的复制项,或者有其他方法可以防止菜单项隐藏在“更多…”后面

更新

这是我重写canPerformAction:withSender:时得到的输出,请注意,从未为“copy:”操作调用该方法:

无法对发件人执行操作剪切:。
无法对发件人执行操作选择。
无法对发件人执行操作selectAll:。
无法对发件人执行操作粘贴。
无法对发件人执行删除操作。
无法对发件人执行操作promptForReplace:。
无法对发件人执行操作\u showMoreItems:。
无法对发件人执行操作_setRtoLTextDirection:。
无法对发件人执行操作\u setLtoRTextDirection:。
可以对发件人执行customCopy:操作。
可以对发件人执行custom1:操作。
无法对发件人执行custom2:操作。
可以对发件人执行操作custom3:。
可以对发件人执行操作custom4:。
无法对发件人执行操作剪切。
无法对发件人执行操作选择。
无法对发件人执行操作selectAll:。
无法对发件人执行操作粘贴。
无法对发件人执行删除操作。
无法对发件人执行操作promptForReplace:。
无法对发件人执行操作\u showMoreItems:。
无法对发件人执行操作_setRtoLTextDirection:。
无法对发件人执行操作\u setLtoRTextDirection:。

您可以绘制自己的菜单,而不必使用UIMenuController。这样,您可以同时显示任意数量的项目,而无需使用其他项目。

您链接的技术似乎仍然有效。我用这些方法实现了一个
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;
}

莱姆纳的回答是正确的。实现UIWebView的子类工作得很好。这对于UITextView来说是正常的。对于UIWebView,创建自定义子类,如下所示:

//
//  MyUIWebView.h
//

#import <UIKit/UIKit.h>

@interface MyUIWebView : UIWebView

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

更新

如果想禁用“复制”,但留下“定义”(和“翻译”),这可能是有用的,这是如何做到的;将上面的
canPerformAction:替换为Sender

-(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的解决方案。Josh Garnham建议创建一个UIWebBrowserView类别来捕获副本:、粘贴:、定义:选择器


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

(您必须键入“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
记录在案,一次“点击”仍然会带来恼人的拼写检查建议!但是,否则它会完全删除双击上下文菜单,苹果100%拒绝了它。

我为我的英语感到抱歉。 但是有一个想法

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


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

对于ios>=5.1 canPerformAction:(SEL)带sender:(id)sender的操作不再工作

如果您同意只禁用粘贴操作,这里有一个方法:

将UITextFieldDelegate添加到视图控制器并实现如下方法

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
if(textField == txtEmailRe)
    return ((string.length) > 1 ? NO : YES);
}
这意味着,若用户为每个操作输入多个字符(这意味着用户可能正在粘贴某些内容),请不要在textfield中接受它


强制用户输入电子邮件和

等文本字段是一种很好的做法。显然,在Objective-C中无法从UIMenuController中删除副本,但可以使用CSS:
-webkit用户选择:无也许我在开头的一段中不够清楚,但我并没有试图阻止用户选择。我试图在UIMenuController中放置多个自定义菜单项,而不会将它们卡在“更多…”菜单下。您过去可以通过阻止Copy命令显示()来实现这一点,但这已经不起作用了。什么是“不再起作用”?它是在iOS5中坏了还是什么的?我所说的“不再工作”是指发布在这里的解决方案:不工作。显然过去是这样。其他人()也发现这个解决方案不起作用。正如我在更新中提到的,重写的方法从未被调用用于“复制:”。@Ifalin您最终找到了新版本的解决方案吗?我仍然在使用此技术,并且可以确认它在iOS 4.3.2中有效。不过,我还没有尝试过iOS5测试版。不,它在iOS5中不适用于默认选择器,如剪切、复制、粘贴、选择、选择全部、定义和建议。即使我返回NO,这些仍然会显示。这在UIExtField或UIWebView中都不起作用。我可以确认它在我的应用程序中起作用,该应用程序是用运行在iOS4和iOS5上的最新iOS5 SDK构建的。我隐藏所有默认的复制/粘贴菜单项,并在自定义UIWebView子类上显示我自己的-全部
@implementation UIWebBrowserView (UIWebBrowserView_Additions)
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    return NO;
}
@end
// .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
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
if(textField == txtEmailRe)
    return ((string.length) > 1 ? NO : YES);
}