I have an app where I load content to a UIWebView
and present this. I cannot disable user interaction completely because I want the user to be able to click links. I just need to disable user selection. I found somewhere in the Internets that you can use:
document.body.style.webkitUserSelect='none';
I tried inserting this as
[self.contentView stringByEvaluatingJavaScriptFromString:@"document.body.style.webkitUserSelect='none';"];
in webViewDidFinishLoad:
However, it does not work. I am still able to select and copy text inside the WebView.
Any Ideas what might be going wrong?
Update: This only seems to happen starting with iOS 4.3
Here are a few ways to disable selection:
<style type="text/css">
* {
-webkit-touch-callout: none;
-webkit-user-select: none; /* Disable selection/copy in UIWebView */
}
</style>
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];
}
I can confirm that the following code works in 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';"];
}
Also works for iOS 9 and later. Here's the swift code:
func webViewDidFinishLoad(webView: UIWebView) {
// Disable user selection
webView.stringByEvaluatingJavaScriptFromString("document.documentElement.style.webkitUserSelect='none'")!
// Disable callout
webView.stringByEvaluatingJavaScriptFromString("document.documentElement.style.webkitTouchCallout='none'")!
}
I am using this technique in a web app for Android / iPhone (packaged with Trigger.IO) and found it would only work with the chaining syntax for the :not() pseudo-class, :
*: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 */
}
I like the WrightsCS solution but I will use this so the users can still using the copy,paste and select actions on inputs
<style type="text/css">
*:not(input,textarea) {
-webkit-touch-callout: none;
-webkit-user-select: none; /* Disable selection/Copy of UIWebView */
}
</style>
I am not sure how the setup is done, but why dont you just clear the pasteBoard when viewWillDisappear is called. Maybe something like in your appDelegate.m:
[UIPasteboard generalPasteboard].string = nil;
this will make sure whatever data user might have copied, they will not be able to paste it outside of the app.
Also, like Engin said you can override the canPerformSelector method in the controller class that contains the uiwebview.
TPoschel answer is corrent but in my case order was important.
// 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';"];
}
I can confirm this will definitely work for you.
<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>
If you want Disable only anchor button tag use this.
a {-webkit-user-select: none; /* disable selection/Copy of UIWebView */
-webkit-touch-callout: none; /* disable the IOS popup when long-press on a link */
}
let longPress:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: nil, action: nil)
longPress.minimumPressDuration = 0.2
webView.addGestureRecognizer(longPress)
Simply add this code to your viewDidLoad(). User can click on link but can not copy the content.
1) Swizzle method (by rentzsch/jrswizzle library):
[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) Place UIWebView on UIView and add a code:
UITapGestureRecognizer* singleTap = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)] autorelease];
singleTap.numberOfTapsRequired = 2;
singleTap.numberOfTouchesRequired = 1;
singleTap.delegate = self;
[self.view addGestureRecognizer:singleTap];
And this one:
- (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;
}
The first solution given worked perfectly for me...until I loaded a .pdf into my UIWebView.
Loading a .doc file worked perfectly, but loading a .pdf resulted in the following line of code no longer having the desired effect and the copy/define menu popped up again on a long touch by the user.
[webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect='none';"];
After another bout of hair pulling I found this answer on here by Johnny Rockex and it worked like a champ. UIWebView without Copy/Paste when displaying PDF files
Many thanks to him for this easy to implement, genius solution!!
For me, I have intended to fetch the images' NSData
from UIWebView
by LongPressGesture
.
But the Magnifier and Copy/Paste/Cut always occur before my func execute.
And I found this:
It means, the the Magnifier and Copy/Paste/Cut need 0.5s to execute, so if your func can be executed in 0.49s, DONE !
self.longPressPan.minimumPressDuration = 0.3
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With