Вимкнення вибору користувача в UIWebView


121

У мене є додаток, куди я завантажую вміст у файл UIWebViewі представляю це. Я не можу повністю відключити взаємодію користувачів, оскільки хочу, щоб користувач міг натискати посилання. Мені просто потрібно відключити вибір користувача. Я десь в Інтернеті знайшов, що ви можете використовувати:

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

Я спробував вставити це як

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

в webViewDidFinishLoad:

Однак це не працює. Я все ще вмію вибирати та копіювати текст у веб-перегляді.

Будь-які ідеї, що може піти не так?

Оновлення: це, здається, відбувається лише починаючи з 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];
}

1
Розширення UIWebViewза допомогою категорії.
Діпак Дандупролу

4
Engin, перший працює в Mobile Safari, iOS 4.3.1. Але WrightCS забув додати селектор. Щоб застосувати його до всіх елементів, використовуйте зірочку, наприклад: * {/ * css йде сюди * /}
fisherwebdev

1
Додавання стилю прекрасно спрацювало з видаленням меню, яке з’явилося під час натискання на посилання всередині моєї програми PhoneGap.
спатичний

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

2
Підтверджено на iOS 7! Примітка. Можна згрупувати два виклики в одному шляхом об'єднання двох рядків.
Bigood

На iOS 9.x порожній дзвінок з’являється у верхній частині екрана після тривалого натискання, навіть при використанні вище.
DwarDoh

як я можу використовувати вищевказаний код .. Я просто знаю JS; Поняття не маю, як я можу редагувати об'єктивний код c або змінити плагін phonegap. Якщо хтось може допомогти
Lakshay

Працюйте з iOS 9 & 10 ідеальним хлопцем!
ΩlostA

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>

2
Якщо ви збираєтесь це робити, не забувайте textarea!
Райан

9

Я не впевнений, як робиться налаштування, але чому ви просто не очистите папку Board, коли викликається viewWillDisappear. Можливо, щось на кшталт вашого appDelegate.m:

[UIPasteboard generalPasteboard].string = nil;

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

Крім того, як Engin сказав, що ви можете змінити метод canPerformSelector в класі контролера, який містить uiwebview.


1
Це одне з найкращих рішень. Це можна встановити в - (недійсній) applicationDidEnterBackground: (UIApplication *) обробник подій програми. Це гарантує, що дані не виходять із програми.
Крішнан

@ Кришан, ти на 100% впевнений, що також припинить знімки екрана?
Норман Н

Мені подобається це рішення, але оскільки він залишається на картонній дошці, поки програма активна, інша (зловмисна) програма, що працює у фоновому потоці, може отримати доступ до загальної картони, поки вона має в ній дані.
binary_falcon

Не хочете це також видалити дані не з програми? Можливо, отримати дані на появі і повернути їх до того, що при зникненні буде працювати краще
Hamzah Malik

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

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, але вимагає двох натискань.
арломедія

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


1
Ласкаво просимо в stackoverflow. Чи дійсно відповідь додає значення цьому старому питанню? Перегляньте, як відповісти .
dbank

1
Спробуйте розширити свою відповідь (надаючи невеликий приклад невеликого коду), щоб збільшити значення своєї відповіді. Крім того, відповіді, що містять "це працює на мене", насправді не викликають впевненості - краще подати відповідь як є, а потім усунути неполадки, якщо хтось попросить роз'яснити вашу відповідь.
Аарон Д
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.