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

121

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

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

Я пробовал вставить это как

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

в webViewDidFinishLoad:

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

Любые идеи, что может пойти не так?

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

Энгин Курутепе
источник

Ответы:

280

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

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

<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];
}
WrightsCS
источник
1
Расширить UIWebViewс помощью категории.
Дипак Дандупролу
4
Энгин, первый работает в Mobile Safari, iOS 4.3.1. Но WrightCS забыл добавить селектор. Чтобы применить его ко всем элементам, используйте звездочку, например: * {/ * css идет сюда * /}
fisherwebdev
1
Добавление стиля отлично сработало при удалении меню, которое появлялось при нажатии на ссылку внутри моего приложения PhoneGap.
spatical
7
canPerformActionне отключает меню Вырезать, Копировать, Вставить. И выберите, выберите все меню. Как это исправить? -webkit-touch-calloutи removeAllRangesпрервать ввод пользователя. Невозможно использовать все предоставленные методы :(
Дмитрий
4
Проблема с помещением этих стилей без выбора в *глобальную область видимости заключается в том, что он останавливает ввод пользователя в веб-формы. Я обнаружил, что лучше помещаю в bodyтег.
Дэвид Дуглас,
104

Я могу подтвердить, что следующий код работает в 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'")!
}
TPoschel
источник
2
Подтверждено на iOS 7! Примечание. Можно сгруппировать два вызова в один, объединив две строки.
Bigood
В iOS 9.x пустой вызов появляется вверху экрана после длительного нажатия, даже при использовании выше.
DwarDoh
как я могу использовать приведенный выше код .. Я просто знаю JS; понятия не имею, как я могу отредактировать код цели c или изменить плагин телефонного разговора ... если кто-нибудь может помочь
Лакшай
Работайте с iOS 9 и 10, идеальный парень!
ΩlostA 08
25

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

}
Джоно Скотт
источник
Я использую jQuery Mobile и Phonegap Build, и это сработало для меня. Я сначала попробовал, *:not(input,textarea) {-webkit-touch-callout: none; -webkit-user-select: none;}но мне это не помогло. Спасибо!
Марк Раммел
18

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

<style type="text/css">
*:not(input,textarea) {
    -webkit-touch-callout: none;
    -webkit-user-select: none; /* Disable selection/Copy of UIWebView */
}
</style>
pablobart
источник
2
Если вы собираетесь это сделать, не забудьте textarea!
Райан
9

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

[UIPasteboard generalPasteboard].string = nil;

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

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

Bittu
источник
1
Это одно из лучших решений. Это можно задать в обработчике событий приложения - (void) applicationDidEnterBackground: (UIApplication *). И это гарантирует, что данные не будут выходить из приложения.
Кришнан
@Krishan, ты на 100% уверен, что скриншоты тоже останутся?
Norman H
Мне нравится это решение, но поскольку оно остается на монтажном столе, пока приложение активно, другое (вредоносное) приложение, работающее в фоновом потоке, может получить доступ к общему монтажному столу, пока в нем есть данные.
binary_falcon
Разве это не удалит данные не из приложения? Возможно, получить данные при появлении и вернуть их к тому, что при исчезновении будет работать лучше
Хамза Малик
7

Ответ 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';"];
}
pawelini1
источник
7

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

<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 */
     }
Нарсинг Томар
источник
5

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

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;
}
Дмитрий
источник
2
Было бы неплохо объяснить, что это должно делать. В частности, меня смущает, почему ваш жест называется singleTap, но требует двух касаний.
arlomedia
5
    let longPress:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: nil, action: nil)
    longPress.minimumPressDuration = 0.2
    webView.addGestureRecognizer(longPress)

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

Самрат Праманик
источник
4

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

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

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

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

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

Скутер
источник
2

Для меня, я предназначен для извлечения изображений NSDataс UIWebViewпомощьюLongPressGesture .

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

И я нашел вот это: введите описание изображения здесь

Это означает, что лупа и копирование / вставка / вырезание требуют 0,5 секунды для выполнения, поэтому, если ваша функция может быть выполнена за 0,49 секунды, ГОТОВО!

self.longPressPan.minimumPressDuration = 0.3
Кайюань Сюй
источник
это работает для меня в iOS 9 + Xcode 7 GM, другие методы, которые я пробовал, просто полезны в iOS 7 и 8
Kaiyuan Xu
-4

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

   webView.userInteractionEnabled = false

Меня устраивает

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

Srohr
источник
1
Добро пожаловать в stackoverflow. Действительно ли ответ добавляет ценности этому старому вопросу? Пожалуйста, прочтите, как ответить .
dbank
1
Попробуйте расширить свой ответ (предоставив небольшой пример кода), чтобы повысить ценность вашего ответа. Кроме того, ответы, содержащие «это работает для меня», на самом деле не внушают доверия - лучше представить ответ как есть, а затем устранить неполадки, если кто-то попросит разъяснений по вашему ответу.
Aaron D