Отключение выбора пользователя в UIWebView - PullRequest
118 голосов
/ 13 мая 2011

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

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

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

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

в webViewDidFinishLoad:

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

Есть идеи, что может пойти не так?

Обновление: похоже, это происходит только с iOS 4.3

Ответы [ 12 ]

274 голосов
/ 19 мая 2011

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

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

<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];
}
102 голосов
/ 02 октября 2012

Я могу подтвердить, что следующий код работает в 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'")!
}
24 голосов
/ 20 января 2013

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

}
18 голосов
/ 03 ноября 2012

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

<style type="text/css">
*:not(input,textarea) {
    -webkit-touch-callout: none;
    -webkit-user-select: none; /* Disable selection/Copy of UIWebView */
}
</style>
9 голосов
/ 25 мая 2011

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

[UIPasteboard generalPasteboard].string = nil;

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

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

7 голосов
/ 21 августа 2014

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

<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 */
     }
7 голосов
/ 29 июля 2014

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';"];
}
5 голосов
/ 09 ноября 2012

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

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;
}
4 голосов
/ 01 января 2014

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

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

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

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

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

3 голосов
/ 21 июля 2017
    let longPress:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: nil, action: nil)
    longPress.minimumPressDuration = 0.2
    webView.addGestureRecognizer(longPress)

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

...