UIWebViewでのユーザー選択の無効化


121

コンテンツをに読み込んで表示するアプリがありますUIWebView。ユーザーがリンクをクリックできるようにしたいため、ユーザー操作を完全に無効にすることはできません。ユーザーの選択を無効にするだけです。私はインターネットのどこかであなたが使える場所を見つけました:

document.body.style.webkitUserSelect='none';

これを挿入してみました

[self.contentView stringByEvaluatingJavaScriptFromString:@"document.body.style.webkitUserSelect='none';"]; 

webViewDidFinishLoad:

ただし、機能しません。WebView内のテキストを選択してコピーできます。

何が問題になっているのでしょうか?

更新:これはiOS 4.3以降でのみ発生するようです

回答:


280

選択を無効にする方法はいくつかあります。

以下をモバイルWebドキュメントに追加します

<style type="text/css">
* {
    -webkit-touch-callout: none;
    -webkit-user-select: none; /* Disable selection/copy in UIWebView */
}
</style>

プログラムで次のJavascriptコードをロードします。

NSString * jsCallBack = @"window.getSelection().removeAllRanges();";    
[webView stringByEvaluatingJavaScriptFromString:jsCallBack];

ユーザーメニューの[コピー/貼り付け]を無効にします。

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender 
{    
    if (action == @selector(copy:) ||
        action == @selector(paste:)||
        action == @selector(cut:)) 
    {
        return _copyCutAndPasteEnabled;
    }
    return [super canPerformAction:action withSender:sender];
}

1
UIWebViewカテゴリを使用して拡張します。
Deepak Danduprolu、2011年

4
Engin、最初のバージョンはMobile Safari、iOS 4.3.1で機能します。しかし、WrightCSはセレクターを追加するのを忘れていました。、すべての要素に適用するように、アスタリスクを使用するには:* {/ * CSSをここに* /}
fisherwebdev

1
スタイルを追加すると、PhoneGapアプリ内のリンクをタップしたときに表示されるメニューが完全に削除されました。
11

7
canPerformAction切り取り、コピー、貼り付けメニューは無効になりません。そして、選択、すべて選択メニュー。これを修正するには?ユーザー入力-webkit-touch-calloutremoveAllRanges中断します。提供されているすべてのメソッドを使用することはできません:(
Dmitry

4
これらの非選択スタイルを*グローバルスコープに配置することの問題は、Webフォームでのユーザー入力が停止することです。body代わりにタグの内側に配置すると、より良い結果が得られることがわかりました。
デビッドダグラス

104

次のコードがiOS 5.0〜8.0で動作することを確認できます。

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    // Disable user selection
    [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect='none';"];
    // Disable callout
    [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitTouchCallout='none';"];
}

iOS 9以降でも動作します。これが迅速なコードです:

func webViewDidFinishLoad(webView: UIWebView) {
    // Disable user selection
    webView.stringByEvaluatingJavaScriptFromString("document.documentElement.style.webkitUserSelect='none'")!
    // Disable callout
    webView.stringByEvaluatingJavaScriptFromString("document.documentElement.style.webkitTouchCallout='none'")!
}

2
iOS 7で確認されました!注:2つの文字列を連結することにより、2つの呼び出しを1つにグループ化することができます。
Bigood 2013

iOS 9.xでは、上記を使用している場合でも、長押しすると画面の上部に空のコールアウトが表示されます。
DwarDoh、2015年

上記のコードをどのように使用できますか。JSを知っています。私がどのように客観的なCコードを編集するか、phonegapプラグインを変更するかについてはわかりません。もし誰かが助けてくれるなら
Lakshay

iOS 9および10の完璧な男と一緒に仕事をしましょう!
ΩlostA

25

私はこのテクニックをAndroid / iPhoneのWebアプリ(Trigger.IOにパッケージされている)で使用していて、:not()擬似クラスのチェーン構文でのみ機能することを発見しました:

*:not(input):not(textarea) {
-webkit-user-select: none; /* disable selection/Copy of UIWebView */
    -webkit-touch-callout: none; /* disable the IOS popup when long-press on a link */

}

私はjQuery MobileとPhonegap Buildを使用していますが、これでうまくいきました。私は最初に試しました*:not(input,textarea) {-webkit-touch-callout: none; -webkit-user-select: none;}が、それは私にとってはうまくいきませんでした。ありがとう!
Mark Rummel、2013

18

私はWrightsCSソリューションが好きですが、これを使用して、ユーザーが入力のコピー、貼り付け、および選択アクションを引き続き使用できるようにします

<style type="text/css">
*:not(input,textarea) {
    -webkit-touch-callout: none;
    -webkit-user-select: none; /* Disable selection/Copy of UIWebView */
}
</style>

2
これを行う場合は、textareaを忘れないでください。
ライアン

9

設定がどのように行われるかはわかりませんが、viewWillDisappearが呼び出されたときにpasteBoardをクリアしないでください。多分あなたのappDelegate.mのようなもの:

[UIPasteboard generalPasteboard].string = nil;

これにより、ユーザーがコピーした可能性のあるデータがすべて確認され、アプリの外にデータを貼り付けることができなくなります。

また、Enginが言ったように、uiwebviewを含むコントローラークラスのcanPerformSelectorメソッドをオーバーライドできます。


1
これは最良のソリューションの1つです。これは-(void)applicationDidEnterBackground:(UIApplication *)applicationイベントハンドラーで設定できます。そして、これにより、データがアプリから送信されなくなります。
クリシュナン

@クリシャン、あなたはスクリーンショットを停止することを100%確信していますか?
ノーマンH

私はこのソリューションが好きですが、アプリケーションがアクティブな間はペーストボードにとどまるため、バックグラウンドスレッドで実行されている別の(悪意のある)アプリケーションがデータを持っている間、一般的なペーストボードにアクセスできます。
binary_falcon 2014

これもアプリからではないデータを削除しませんか?おそらく、データを表示して取得し、それを非表示に設定すると、うまくいくでしょう
Hamzah Malik

7

TPoschelの答えは正しいですが、私の場合は順序が重要でした。

// this works - locks selection and callout
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect='none';"];
    [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitTouchCallout='none';"];
}

// this doesn't work - locks only callout
- (void)webViewDidFinishLoad:(UIWebView *)webView {
    [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitTouchCallout='none';"];
    [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect='none';"];
}

7

これが間違いなく機能することを確認できます。

<style type="text/css">
  *:not(input):not(textarea) {
   -webkit-user-select: none; /* disable selection/Copy of UIWebView */
   -webkit-touch-callout: none; /* disable the IOS popup when long-press on a link */
   }       
</style>

アンカーボタンタグのみを無効にする場合は、これを使用します。

    a {-webkit-user-select: none; /* disable selection/Copy of UIWebView */
   -webkit-touch-callout: none; /* disable the IOS popup when long-press on a link */
     }

5

1週間の大作の結果!多くのページでマウスイベントとユーザー入力を保存する場合、その他すべての回答は正しくありません。

1)Swizzleメソッド(rentzsch / jrswizzleライブラリによる):

[NSClassFromString(@"UIWebDocumentView") jr_swizzleMethod:@selector(canPerformAction:withSender:) withMethod:@selector(myCanPerformAction:withSender:) error:nil];

NSObject + myCanPerformAction.h:

@interface NSObject (myCanPerformAction)

- (BOOL)myCanPerformAction:(SEL)action withSender:(id)sender;

@end

NSObject + myCanPerformAction.m:

#import "NSObject+myCanPerformAction.h"

@implementation NSObject (myCanPerformAction)

- (BOOL)myCanPerformAction:(SEL)action withSender:(id)sender {
    if (action == @selector(copy:)) {
        return [self myCanPerformAction:action withSender:sender];
    }
    if (action == @selector(paste:)) {
        return [self myCanPerformAction:action withSender:sender];
    }
    return NO;
}

@end

2)UIWebViewをUIViewに配置し、コードを追加します。

    UITapGestureRecognizer* singleTap = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)] autorelease];
    singleTap.numberOfTapsRequired = 2;
    singleTap.numberOfTouchesRequired = 1;
    singleTap.delegate = self;
    [self.view addGestureRecognizer:singleTap];

そしてこれ:

- (void)handleSingleTap:(UIGestureRecognizer*)gestureRecognizer {
    return;
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    if ([otherGestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
        UITapGestureRecognizer *gesture = (UITapGestureRecognizer *)otherGestureRecognizer;
        if (gesture.numberOfTapsRequired == 2) {
            [otherGestureRecognizer.view removeGestureRecognizer:otherGestureRecognizer];
        }
    }
    return YES;
}

2
これが何をすべきかについてのいくつかの説明がいいでしょう。特に、ジェスチャーがシングルタップと呼ばれているのに2タップが必要な理由について混乱しています。
arlomedia 2014

5
    let longPress:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: nil, action: nil)
    longPress.minimumPressDuration = 0.2
    webView.addGestureRecognizer(longPress)

このコードをviewDidLoad()に追加するだけです。ユーザーはリンクをクリックできますが、コンテンツをコピーできません。


4

与えられた最初のソリューションは私にとって完璧に機能しました... UIWebViewに.pdfをロードするまで。

.docファイルの読み込みは完全に機能しましたが、.pdfを読み込むと、次のコード行では目的の効果が得られなくなり、ユーザーが長い間触れるとコピー/定義メニューが再びポップアップしました。

    [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect='none';"];

髪を引っ張ってもう一度試してみたところ、ジョニー・ロックスがここでこの答えを見つけたので、それは大げさなように機能しました。 PDFファイルを表示するときのコピー/貼り付けなしのUIWebView

この簡単に実装できる天才的なソリューションを彼に感謝します!!


2

私にとっては、by NSDataから画像をフェッチするつもりでしUIWebViewLongPressGesture

しかし、拡大鏡とコピー/貼り付け/切り取りは、常にfuncが実行される前に発生します。

そして私はこれを見つけました: ここに画像の説明を入力してください

つまり、拡大鏡とコピー/貼り付け/切り取りを実行するには0.5秒必要なので、funcを0.49秒で実行できれば、完了です!

self.longPressPan.minimumPressDuration = 0.3

これは私にとってiOS 9 + Xcode 7 GMで機能し、私が試した他の方法はiOS 7と8で便利です
Kaiyuan Xu

-4

Webビューの交差機能を使用する

   webView.userInteractionEnabled = false

わたしにはできる

PS:ユーザーがウェブビューをもう一度操作できるようにしたい場合は、操作を有効に戻すことを忘れないでください


1
Stackoverflowへようこそ。答えは本当にこの古い質問に価値を加えますか?回答方法を確認してください。
dbank 2015年

1
回答の価値を高めるために、回答を拡張する(小さなコード例を提供する)ことを検討してください。また、「それは私にとってはうまくいく」を含む回答は本当に自信を刺激するものではありません。回答を現状のまま提示し、誰かがあなたの回答についての説明を求めた場合のトラブルシューティングを行うことをお勧めします。
アーロンD
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.