Tắt lựa chọn người dùng trong UIWebView


121

Tôi có một ứng dụng mà tôi tải nội dung vào a UIWebViewvà trình bày cái này. Tôi không thể tắt hoàn toàn tương tác của người dùng vì tôi muốn người dùng có thể nhấp vào liên kết. Tôi chỉ cần vô hiệu hóa lựa chọn người dùng. Tôi tìm thấy một nơi nào đó trong Internets mà bạn có thể sử dụng:

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

Tôi đã thử chèn cái này dưới dạng

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

trong webViewDidFinishLoad:

Tuy nhiên, nó không hoạt động. Tôi vẫn có thể chọn và sao chép văn bản bên trong WebView.

Bất kỳ ý tưởng những gì có thể xảy ra sai?

Cập nhật: Điều này dường như chỉ xảy ra bắt đầu với iOS 4.3

Câu trả lời:


280

Dưới đây là một số cách để tắt lựa chọn:

Thêm phần sau vào tài liệu web di động của bạn

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

Tải theo chương trình mã Javascript sau:

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

Tắt menu người dùng Sao chép / Dán:

- (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
Mở rộng UIWebViewbằng cách sử dụng một danh mục.
Deepak Danduprolu

4
Engin, cái đầu tiên hoạt động trong Mobile Safari, iOS 4.3.1. Nhưng WrightCS đã quên thêm bộ chọn. Để áp dụng nó cho tất cả các phần tử, hãy sử dụng dấu hoa thị, như: * {/ * css vào đây * /}
fishwebdev

1
Thêm kiểu đã hoạt động hoàn hảo khi xóa menu xuất hiện khi nhấn vào liên kết bên trong ứng dụng PhoneGap của tôi.
spatical

7
canPerformActionkhông tắt menu Cắt, Sao chép, Dán. Và Chọn, Chọn Tất cả menu. Làm thế nào để khắc phục điều này? -webkit-touch-calloutremoveAllRangesphá vỡ đầu vào của người dùng. Không thể sử dụng tất cả các phương pháp được cung cấp :(
Dmitry

4
Vấn đề với việc đưa các kiểu không chọn này vào *phạm vi toàn cầu là nó dừng việc nhập của người dùng vào các biểu mẫu web. bodyThay vào đó, tôi nhận thấy mình nhận được kết quả tốt hơn bằng cách đặt bên trong thẻ.
David Douglas

104

Tôi có thể xác nhận rằng mã sau hoạt động trong 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';"];
}

Cũng hoạt động cho iOS 9 trở lên. Đây là mã nhanh:

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

2
Đã xác nhận trên iOS 7! Lưu ý: Có thể nhóm hai cuộc gọi thành một bằng cách nối hai chuỗi.
Bigood 13/1213

Trên iOS 9.x, một cuộc gọi trống xuất hiện ở đầu màn hình sau khi nhấn và giữ, ngay cả khi sử dụng ở trên.
DwarDoh

làm thế nào tôi có thể sử dụng mã trên .. Tôi chỉ biết JS; không có bất kỳ ý tưởng làm thế nào tôi có thể chỉnh sửa mã khách quan c hoặc thay đổi PhoneGap plugin..if ai có thể giúp
Lakshay

Làm việc với anh chàng hoàn hảo iOS 9 & 10!
ΩlostA

25

Tôi đang sử dụng kỹ thuật này trong một ứng dụng web dành cho Android / iPhone (được đóng gói với Trigger.IO) và nhận thấy rằng nó sẽ chỉ hoạt động với cú pháp chuỗi cho: 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 */

}

Tôi đang sử dụng jQuery Mobile và Phonegap Build và điều này phù hợp với tôi. Tôi đã thử lần đầu tiên *:not(input,textarea) {-webkit-touch-callout: none; -webkit-user-select: none;}, nhưng điều đó không phù hợp với tôi. Cảm ơn!
Mark Rummel

18

Tôi thích giải pháp WrightsCS nhưng tôi sẽ sử dụng giải pháp này để người dùng vẫn có thể sử dụng các thao tác sao chép, dán và chọn trên đầu vào

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

2
Nếu bạn định làm điều này, đừng quên textarea!
Ryan

9

Tôi không chắc quá trình thiết lập được thực hiện như thế nào, nhưng tại sao bạn không xóa pasteBoard khi viewWillDisappear được gọi. Có thể một cái gì đó giống như trong ứng dụng của bạnDelegate.m:

[UIPasteboard generalPasteboard].string = nil;

điều này sẽ đảm bảo bất kỳ dữ liệu nào người dùng có thể đã sao chép, họ sẽ không thể dán dữ liệu đó ra bên ngoài ứng dụng.

Ngoài ra, giống như Engin đã nói, bạn có thể ghi đè phương thức canPerformSelector trong lớp bộ điều khiển có chứa uiwebview.


1
Đây là một trong những giải pháp tốt nhất. Điều này có thể được đặt trong - (void) applicationDidEnterBackground: (UIApplication *) trình xử lý sự kiện ứng dụng. Và điều này đảm bảo rằng không có dữ liệu nào đi ra khỏi Ứng dụng.
Krishnan

@Krishan, bạn có chắc chắn 100% rằng sẽ dừng ảnh chụp màn hình không?
Norman H

Tôi thích giải pháp này, nhưng vì nó vẫn ở trên bảng dán trong khi ứng dụng đang hoạt động, một ứng dụng (độc hại) khác đang chạy trong chuỗi nền có thể truy cập bảng dán chung khi có dữ liệu trong đó.
binary_falcon

Điều này sẽ không xóa dữ liệu không phải từ ứng dụng? Có lẽ lấy dữ liệu tại xuất hiện và đặt nó trở lại rằng trên biến mất sẽ làm việc tốt hơn
Hamzah Malik

7

Câu trả lời TPoschel là đúng nhưng trong trường hợp của tôi, thứ tự là quan trọng.

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

Tôi có thể khẳng định điều này chắc chắn sẽ hiệu quả với bạn.

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

Nếu bạn muốn Vô hiệu hóa chỉ thẻ nút liên kết sử dụng thẻ này.

    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

Kết quả của công việc tuyệt vời trong một tuần! Tất cả các câu trả lời khác đều không chính xác nếu bạn muốn lưu các sự kiện chuột và thông tin nhập của người dùng trên nhiều trang.

1) Phương pháp Swizzle (theo thư viện 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) Đặt UIWebView trên UIView và thêm mã:

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

Và cái này nữa:

- (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
Một số giải thích về những gì điều này được cho là sẽ làm sẽ tốt. Đặc biệt, tôi bối rối về lý do tại sao cử chỉ của bạn được gọi là SingleTap nhưng lại yêu cầu hai lần nhấn.
arlomedia

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

Chỉ cần thêm mã này vào viewDidLoad () của bạn. Người dùng có thể nhấp vào liên kết nhưng không thể sao chép nội dung.


4

Giải pháp đầu tiên được đưa ra đã hoạt động hoàn hảo cho tôi ... cho đến khi tôi tải tệp .pdf vào UIWebView của mình.

Việc tải tệp .doc hoạt động hoàn hảo, nhưng việc tải tệp .pdf dẫn đến dòng mã sau đây không còn có tác dụng như mong muốn và trình đơn sao chép / xác định lại xuất hiện khi người dùng chạm lâu.

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

Sau một hồi giật tóc, tôi đã tìm thấy câu trả lời này của Johnny Rockex ở đây và nó hoạt động như một nhà vô địch. UIWebView không có Sao chép / Dán khi hiển thị các tệp PDF

Rất cám ơn anh ấy vì giải pháp thiên tài, dễ thực hiện này !!


2

Đối với tôi, tôi đã có ý định lấy những hình ảnh NSDatatừ UIWebViewbởiLongPressGesture .

Nhưng Kính lúp và Sao chép / Dán / Cắt luôn xảy ra trước khi func của tôi thực thi.

Và tôi tìm thấy điều này: nhập mô tả hình ảnh ở đây

Nó có nghĩa là Kính lúp và Sao chép / Dán / Cắt cần 0,5 giây để thực thi, vì vậy nếu func của bạn có thể được thực thi trong 0,49 giây, HÃY XONG!

self.longPressPan.minimumPressDuration = 0.3

công trình này cho tôi trong iOS 9 + Xcode 7 GM, các phương pháp khác tôi đã cố gắng chỉ là hữu ích trong iOS 7 & 8
Kaiyuan Xu

-4

Sử dụng chức năng tương tác chế độ xem web

   webView.userInteractionEnabled = false

Nó phù hợp với tôi

Tái bút: hãy nhớ bật lại tương tác khi bạn muốn người dùng có thể tương tác lại với chế độ xem web


1
Chào mừng bạn đến với stackoverflow. Câu trả lời có thực sự làm tăng giá trị cho câu hỏi cũ này không? Vui lòng xem lại Cách trả lời .
dbank

1
Cân nhắc mở rộng câu trả lời của bạn (cung cấp một số ví dụ mã nhỏ) để tăng giá trị cho câu trả lời của bạn. Ngoài ra, các câu trả lời có chứa 'nó phù hợp với tôi' không thực sự truyền cảm hứng cho sự tự tin - tốt hơn là hãy trình bày câu trả lời như hiện tại và sau đó gỡ rối nếu ai đó yêu cầu làm rõ câu trả lời của bạn.
Aaron D
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.