Отключение выбора пользователя в UIWebView


у меня есть приложение, где я загрузить контент UIWebView и представить это. Я не могу полностью отключить взаимодействие с пользователем, потому что я хочу, чтобы пользователь мог нажимать ссылки. Мне просто нужно отключить выбор пользователя. Я нашел где-то в интернете, что вы можете использовать:

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

Я попытался вставить это как

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

на webViewDidFinishLoad:

однако, это не работает. Я все еще могу выбрать и скопировать текст внутри WebView.

любые идеи, что может быть не так?

Update: это только кажется, происходит начиная с iOS 4.3

12 113

12 ответов:

вот несколько способов отключить выбор:

добавьте следующее в свои мобильные веб-документы

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

Я могу подтвердить, что следующий код работает в 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 и более поздних версий. Вот swift-код:

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

Я использую этот метод в веб-приложении для Android / iPhone (в комплекте с 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 */

}

Мне нравится решение WrightsCS, но я буду использовать это, чтобы пользователи все еще могли использовать действия копирования,вставки и выбора на входах

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

Я не уверен, как выполняется настройка, но почему бы вам просто не очистить pasteBoard при вызове viewWillDisappear. Может быть, что-то вроде в вашем appDelegate.м:

[UIPasteboard generalPasteboard].string = nil;

Это позволит убедиться, что любой пользователь данных, возможно, скопировали, они не смогут вставить его за пределами приложения.

кроме того, как сказал Engin, вы можете переопределить метод canPerformSelector в классе контроллера, который содержит uiwebview.

TPoschel ответ corrent, но в моем случае порядок был важен.

// 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';"];
}

Я могу подтвердить, что это определенно будет работать для вас.

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

результат большой работы за одну неделю! Все остальные ответы неверны если вы хотите сохранить события мыши и ввод пользователя на многих страницах.

1) Метод Swizzle (by исследование процесса самоорганизации/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.м:

#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;
}

первое решение, данное отлично работало для меня...пока я не загрузил .pdf в мой UIWebView.

загрузка a .файл doc работал отлично, но загрузка a .pdf привел к тому, что следующая строка кода больше не имела желаемого эффекта, и меню копирования/определения снова появилось при длительном прикосновении пользователя.

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

после еще одного приступа дергания за волосы я нашел этот ответ здесь Джонни Рокекс, и он работал как чемпион. UIWebView без копирования / вставки, когда отображение PDF файлов

большое спасибо ему за это простое в реализации, гениальное решение!!

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

просто добавьте этот код в viewDidLoad (). Пользователь может нажать на ссылку, но не может скопировать содержимое.

для меня, я намеревался принести изображения'NSData С UIWebView by LongPressGesture.

но лупа и копирование / вставка / вырезание всегда происходят до выполнения моей функции.

и я нашел это: enter image description here

это означает, что лупа и копировать / вставить / вырезать нужно 0.5 s для выполнения, так что если ваш func может быть выполнен в 0.49 s, готово !

self.longPressPan.minimumPressDuration = 0.3

используйте функцию веб-просмотра interection

   webView.userInteractionEnabled = false

это работает для меня

PS: Не забудьте включить взаимодействие обратно, когда вы хотите, чтобы пользователь мог взаимодействовать с webview снова