在UIWebView中禁用用户选择


121

我有一个应用程序,我将内容加载到UIWebView并显示此内容。我无法完全禁用用户交互,因为我希望用户能够单击链接。我只需要禁用用户选择。我在互联网上发现了可以使用的地方:

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

我尝试将其插入为

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

webViewDidFinishLoad:

但是,它不起作用。我仍然可以在WebView中选择和复制文本。

任何想法可能出了什么问题?

更新:这似乎仅从iOS 4.3开始发生

Answers:


280

以下是禁用选择的几种方法:

将以下内容添加到您的移动网络文档中

<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 2011年

1
添加样式可以完美地删除在按住PhoneGap应用程序内部链接时出现的菜单。
spatical

7
canPerformAction不会禁用“剪切,复制,粘贴”菜单。并选择,选择所有菜单。如何解决?-webkit-touch-calloutremoveAllRanges中断用户输入。无法使用所有提供的方法:(
Dmitry

4
将这些no select样式置于*全局范围内的问题在于,它会停止用户在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上确认!注意:可以通过串联两个字符串将两个调用组合在一起。
Bigood

在iOS 9.x上,长按后即使在上方使用时,屏幕顶部也会显示一个空的标注。
DwarDoh,2015年

我该如何使用上面的代码。不知道我如何编辑目标C代码或更改phonegap插件。.如果有人可以帮助
Lakshay

与iOS 9和10完美人一起工作!
ΩlostA

25

我在Android / iPhone(与Trigger.IO打包)的Web应用程序中使用了此技术,发现它仅适用于: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;}但这对我没有帮助。谢谢!
马克·鲁梅尔

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时不清除粘贴板。也许像您的appDelegate.m中那样:

[UIPasteboard generalPasteboard].string = nil;

这样可以确保用户复制了任何数据,他们将无法将其粘贴到应用程序外部。

另外,就像Engin所说的那样,您可以在包含uiwebview的控制器类中覆盖canPerformSelector方法。


1
这是最好的解决方案之一。可以在-(void)applicationDidEnterBackground:(UIApplication *)应用程序事件处理程序中设置。这样可以确保没有数据流出应用程序。
克里希南

@Krishan,您是否100%确定也会停止截图?
Norman H

我喜欢这种解决方案,但是由于在应用程序处于活动状态时它仍位于粘贴​​板上,因此在后台线程中运行的另一个(恶意)应用程序可以在其中包含数据的情况下访问常规粘贴板。
binary_falcon 2014年

这样还会从应用程序中删除数据吗?也许得到的显示数据,并将其设置回上消失,会更好地工作
哈姆扎·马利克

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)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
对此应该做些什么的解释会很好。特别是,我对为什么将您的手势称为singleTap却需要两次轻按感到困惑。
arlomedia 2014年

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

只需将此代码添加到您的viewDidLoad()中。用户可以单击链接,但不能复制内容。


4

给出的第一个解决方案非常适合我...直到将.pdf加载到UIWebView中。

加载.doc文件效果很好,但是加载.pdf导致以下代码行不再具有所需的效果,并且用户长时间触摸后会再次弹出“复制/定义”菜单。

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

又一束头发拉开后,我在这里找到了约翰尼·洛克克斯(Johnny Rockex)的答案,它的工作原理像冠军一样。 显示PDF文件时没有复制/粘贴的UIWebView

非常感谢他提供了这种易于实施的天才解决方案!!


2

对于我来说,我已经打算获取的图像NSDataUIWebView通过LongPressGesture

但是放大镜和复制/粘贴/剪切总是在我执行功能之前发生。

我发现了: 在此处输入图片说明

这意味着,放大镜和复制/粘贴/剪切需要0.5s才能执行,因此,如果您的func可以在0.49s内执行,请完成!

self.longPressPan.minimumPressDuration = 0.3

这在iOS 9 + Xcode 7 GM中对我有效,我尝试过的其他方法在iOS 7&8中也很有用
Xu Kaiyuan Xu

-4

使用网络视图交互功能

   webView.userInteractionEnabled = false

这个对我有用

PS:记住,当您希望用户可以再次与Webview交互时,请启用交互功能


1
欢迎来到stackoverflow。答案是否真的为这个旧问题增加了价值?请查看如何回答
dbank

1
考虑扩展您的答案(提供一些小代码示例)以增加您的答案的价值。另外,包含“对我有用”的答案并不能真正激发信心-最好按现状显示答案,然后解决是否有人要求您对答案进行澄清的问题。
亚伦D
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.