Disabling user selection in UIWebView

96,982

Solution 1

Here are a few ways to disable selection:

Add the following to your mobile web documents

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

Programmatically load the following Javascript code:

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

Disable the Copy / Paste user menu:

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

Solution 2

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'")!
}

Solution 3

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 */

}

Solution 4

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>

Solution 5

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.

Share:
96,982
Engin Kurutepe
Author by

Engin Kurutepe

Indie developer and founder Fifteen Jugglers Software building Aufwind, SolarWatch and CallTap. You can best reach me on Twitter: @ekurutepe

Updated on May 28, 2020

Comments

  • Engin Kurutepe
    Engin Kurutepe almost 4 years

    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

  • Engin Kurutepe
    Engin Kurutepe about 13 years
    Hi Wright, unfortunately the first one does not work in iOS 4.3. Where should I implement the second one? I tried webViewDidFinishLoad: but it didn't work. I also tried the third method in my view controller who is responsible for the UIWebView. It keep returning NO but this doesn't prevent the UIWebView from showing the menu.
  • Deepak Danduprolu
    Deepak Danduprolu about 13 years
    Extend UIWebView using a category.
  • fisherwebdev
    fisherwebdev almost 13 years
    Engin, the first one does work in Mobile Safari, iOS 4.3.1. But WrightCS forgot to add the selector. To apply it to all elements, use the asterisk, like: * { /*css goes here*/ }
  • spatical
    spatical over 12 years
    Adding the style worked perfectly in removing the menu that appeared when tapholding on a link inside of my PhoneGap app.
  • RK-
    RK- over 12 years
    This is one of the best solutions. This can be set in - (void)applicationDidEnterBackground:(UIApplication *)application event handler. And this ensures that no data goes out of the App.
  • Dmitry
    Dmitry over 11 years
    canPerformAction doesn't disable Cut, Copy, Paste menu. And Select, Select All menu. How to fix this? -webkit-touch-callout and removeAllRanges break user input. Can't use all provided methods:(
  • Ryan
    Ryan over 11 years
    If you're going to do this, don't forget textarea!
  • Mark Rummel
    Mark Rummel over 11 years
    I'm using jQuery Mobile and Phonegap Build and this worked for me. I first tried, *:not(input,textarea) {-webkit-touch-callout: none; -webkit-user-select: none;}, but that didn't do the trick for me. Thanks!
  • Norman H
    Norman H almost 11 years
    @Krishan, are you 100% certain that will stop screenshots as well?
  • Bigood
    Bigood over 10 years
    Confirmed on iOS 7! Note : It's possible to group the two calls in one by concatenating the two strings.
  • binary_falcon
    binary_falcon over 9 years
    I like this solution, but since it stays on the pasteboard while the application is active, another (malicious) application running in the background thread can access the general pasteboard while it has data in it.
  • arlomedia
    arlomedia over 9 years
    Some explanation of what this is supposed to do would be nice. In particular, I'm confused about why your gesture is called singleTap but requires two taps.
  • dbank
    dbank about 9 years
    Welcome to stackoverflow. Does answer really add value to this old question? Please review How to Answer.
  • Aaron D
    Aaron D about 9 years
    Consider expanding your answer (providing some small code example) to increase the value of your answer. Also, answers containing 'it works for me' don't really inspire confidence - better to present the answer as-is and then troubleshoot if someone asks for clarification on your answer.
  • SwathiK
    SwathiK about 9 years
    How to add this in my document <style type="text/css"> * { -webkit-touch-callout: none; -webkit-user-select: none; /* Disable selection/copy in UIWebView */ } </style> Shall i do copy paste in the document
  • David Douglas
    David Douglas almost 9 years
    The problem with putting these no select styles in * global scope is that it stops user input in web forms. I found I got better results by placing inside the body tag instead.
  • Kaiyuan Xu
    Kaiyuan Xu over 8 years
    this works for me in iOS 9 + Xcode 7 GM, other methods I tried are just useful in iOS 7&8
  • DwarDoh
    DwarDoh over 8 years
    On iOS 9.x an empty call out appears at top of screen after long press, even when using above.
  • Lakshay Dulani
    Lakshay Dulani about 8 years
    how can I use the above code..I just know JS; don't have any idea how I can edit objective c code or change phonegap plugin..if anybody can help
  • ΩlostA
    ΩlostA over 7 years
    Work with iOS 9 & 10 perfect guy!
  • Hamzah Malik
    Hamzah Malik over 6 years
    wouldnt this also remove data not from the app? Perhaps get the data at appear and set it back to that on disappear would work better
  • bleepmeh
    bleepmeh over 5 years
    @DeepakDanduprolu I have extended UIWebView and used the debugger to make sure it reaches to the function and it returns NO, but copy paste and cut still show up on the menu. Do you have an example possibly?
  • Chris Ho
    Chris Ho over 4 years
    Save my time, Thank you!!