web-dev-qa-db-ja.com

UIMenuControllerからコピーを本当に削除するにはどうすればよいですか

複数のカスタムメニュー項目を追加したときに「More ...」ラベルが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:を除くすべてのシステムメニュー項目に対して呼び出されるため、結果として、システムコピーメニュー項目が常に表示されます。これは、複数のカスタムメニュー項目がある場合、それらは常に「詳細...」の背後に隠されていることを意味します。

それで、システムのコピーアイテムを実際に削除する方法、またはメニューアイテムが「もっと...」の後ろに隠れないようにする別の方法はありますか?

更新

これは、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>.
21
lfalin

リンクしたテクニックはまだ機能しているようです。これらのメソッドを使用して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;
}
13
lemnar

for ios> = 5.1 canPerformAction:(SEL)action withSender:(id)senderが機能しなくなりました。

貼り付けアクションを無効にするだけで問題がない場合は、次の方法があります。

uITextFieldDelegateをビューコントローラーに追加し、次のようなメソッドを実装します

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

これは、ユーザーがアクションごとに複数の文字を入力した場合(おそらくユーザーが何かを貼り付けていることを意味します)、テキストフィールドでそれを受け入れないことを意味します。

ユーザーに電子メールやメールなどのテキストフィールドを強制的に入力することをお勧めします。

7
Canberk Ersoy

これが私のために働くiOS5.xのための解決策です。これはJoshGarnhamによるもので、コピー:、貼り付け:、定義:セレクターをキャッチするためにUIWebBrowserViewカテゴリを作成することを提案しています。

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だけに注意してください:その優れたWebページにはわずかなタイプミスがあります。これがまさにあなたがそれをする方法です。 Apple will100%これを拒否します。カテゴリを作成します

enter image description here

(Xcodeはプライベートクラスを表示しないため、「UIWebBrowserView」と入力する必要があります。)。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

ちなみに、「シングルクリック」でも迷惑なスペルチェッカーの提案が表示されます。ただし、それ以外の場合は、ダブルクリックのコンテキストメニューが完全に削除され、Appleによって100%拒否されます。

3
auco

lemnarの答えは正しいです。 UIWebViewのサブクラスの実装は問題なく機能します。この はUITextViewで問題ありません。 UIWebViewの場合、次のようにカスタムサブクラスを作成します。

//
//  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を次のように置き換えます。

-(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];
}
3
Adriano Lucas

英語でごめんなさい。しかし、アイデアがあります。

CanPerformActionメソッドは何度も呼び出されたと思いますが、一度処理するだけです。この場合、別のUIコントロールがそれを呼び出している可能性があると思います。たとえば、UIWebViewのUITextViewコントロール。

ストーリーボードでUIを生成できると思います。ストーリーボードのすべてのコントロールに独自のクラスがあるわけではありません。応答コントロールのクラスを定義し、そのcanPerformActionメソッドを書き直すことができます。

1
sandycs

UIMenuControllerを使用する代わりに、独自のメニューを描画することもできます。そうすれば、Otherを使用せずに、必要な数のアイテムを同時に表示できます。

0
LaC