UIWebView'da kullanıcı seçimini devre dışı bırakma


121

A'ya içerik yüklediğim ve bunu sunduğum bir uygulamam var UIWebView. Kullanıcı etkileşimini tamamen devre dışı bırakamıyorum çünkü kullanıcının bağlantıları tıklayabilmesini istiyorum. Sadece kullanıcı seçimini devre dışı bırakmam gerekiyor. İnternette kullanabileceğiniz bir yer buldum:

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

Bunu olarak eklemeyi denedim

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

içinde webViewDidFinishLoad:

Ancak çalışmıyor. Hala Web Görünümü içindeki metni seçip kopyalayabiliyorum.

Neyin yanlış gidebileceğine dair herhangi bir fikriniz var mı?

Güncelleme: Bu yalnızca iOS 4.3'ten başlayarak gerçekleşiyor gibi görünüyor

Yanıtlar:


280

Seçimi devre dışı bırakmanın birkaç yolu:

Aşağıdakileri mobil web belgelerinize ekleyin

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

Aşağıdaki Javascript kodunu programlı olarak yükleyin:

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

Kopyala / Yapıştır kullanıcı menüsünü devre dışı bırakı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
UIWebViewBir kategori kullanarak genişletin .
Deepak Danduprolu

4
Engin, ilki Mobile Safari, iOS 4.3.1'de çalışıyor. Ancak WrightCS, seçiciyi eklemeyi unuttu. Bunu tüm öğelere uygulamak için yıldız işaretini kullanın, örneğin: * {/ * css buraya
yazılır

1
Stil eklemek, PhoneGap uygulamamın içindeki bir bağlantıya dokunurken görünen menüyü kaldırmada mükemmel çalıştı.
mekansal olarak

7
canPerformActionKes, Kopyala, Yapıştır menüsünü devre dışı bırakmaz. Ve Seç, Tümünü Seç menüsü. Bunu nasıl düzeltebilirim? -webkit-touch-calloutve removeAllRangeskullanıcı girdisini bozun. Sağlanan tüm yöntemler kullanılamıyor :(
Dmitry

4
Bu seçilmeyen stilleri *genel kapsamda koymakla ilgili sorun , web formlarında kullanıcı girişini durdurmasıdır. Bunun bodyyerine etiketin içine yerleştirerek daha iyi sonuçlar aldığımı fark ettim .
David Douglas

104

Aşağıdaki kodun iOS 5.0 - 8.0'da çalıştığını onaylayabilirim.

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    // Disable user selection
    [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitUserSelect='none';"];
    // Disable callout
    [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitTouchCallout='none';"];
}

Ayrıca iOS 9 ve sonraki sürümler için de çalışır. İşte hızlı kod:

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

2
İOS 7'de onaylandı! Not: İki dizeyi birleştirerek iki çağrıyı bir arada gruplamak mümkündür.
Bigood

İOS 9.x'te, yukarıyı kullanırken bile, uzun süre basıldıktan sonra ekranın üstünde boş bir çağrı görünüyor.
DwarDoh

yukarıdaki kodu nasıl kullanabilirim..Sadece JS'yi biliyorum; objektif c kodunu nasıl düzenleyebileceğimi veya phonegap eklentisini nasıl değiştirebileceğimi bilmiyorum .. eğer kimse yardımcı olabilirse
Lakshay

İOS 9 ve 10 ile çalışın mükemmel adam!
ΩlostA

25

Bu tekniği Android / iPhone için bir web uygulamasında (Trigger.IO ile paketlenmiş) kullanıyorum ve yalnızca: not () sözde sınıfı için zincirleme sözdizimi ile çalışacağını buldum:

*: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 ve Phonegap Build kullanıyorum ve bu benim için çalıştı. İlk önce denedim, *:not(input,textarea) {-webkit-touch-callout: none; -webkit-user-select: none;}ama bu benim için işe yaramadı. Teşekkürler!
Mark Rummel

18

WrightsCS çözümünü beğendim ama bunu kullanacağım, böylece kullanıcılar girdiler üzerinde kopyalama, yapıştırma ve eylemleri seçmeye devam edebilir

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

2
Bunu yapacaksanız, metin alanını unutmayın!
Ryan

9

Kurulumun nasıl yapıldığından emin değilim, ama viewWillDisappear çağrıldığında neden pasteBoard'u temizlemiyorsunuz? Belki appDelegate.m'deki gibi bir şey:

[UIPasteboard generalPasteboard].string = nil;

bu, kullanıcının kopyalamış olabileceği verileri garanti eder, uygulamanın dışına yapıştıramaz.

Ayrıca, Engin'in dediği gibi uiwebview içeren denetleyici sınıfındaki canPerformSelector yöntemini geçersiz kılabilirsiniz.


1
Bu en iyi çözümlerden biridir. Bu, - (void) applicationDidEnterBackground: (UIApplication *) uygulama olay işleyicisinde ayarlanabilir. Ve bu, Uygulamadan hiçbir verinin çıkmamasını sağlar.
Krishnan

@Krishan, bunun ekran görüntülerini de durduracağından% 100 emin misin?
Norman H

Bu çözümü beğendim, ancak uygulama etkinken çalışma alanında kaldığı için arka planda çalışan başka bir (kötü amaçlı) uygulama, içinde veri varken genel çalışma alanına erişebilir.
binary_falcon

bu, uygulamadan olmayan verileri de kaldırmaz mı? Belki de verileri görünün ve geri alın, ortadan kaybolduğunda daha iyi çalışacaktır
Hamzah Malik

7

TPoschel cevabı doğru ama benim durumumda sıra önemliydi.

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

Bunun sizin için kesinlikle işe yarayacağını teyit edebilirim.

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

Yalnızca bağlantı düğmesi etiketini devre dışı bırakmak istiyorsanız bunu kullanın.

    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

Bir haftalık harika çalışmanın sonucu! Fare olaylarını ve birçok sayfaya kullanıcı girişini kaydetmek istiyorsanız diğer tüm cevaplar yanlıştır.

1) Swizzle yöntemi ( rentzsch / jrswizzle kitaplığı ile):

[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'a yerleştirin ve bir kod ekleyin:

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

Ve bu:

- (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
Bunun ne yapması gerektiğine dair bazı açıklamalar güzel olurdu. Özellikle, hareketinizin neden singleTap olarak adlandırıldığı, ancak iki dokunma gerektirdiği konusunda kafam karıştı.
arlomedia

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

Bu kodu viewDidLoad () 'a eklemeniz yeterlidir. Kullanıcı bağlantıya tıklayabilir ancak içeriği kopyalayamaz.


4

Verilen ilk çözüm, UIWebView'uma bir .pdf yükleyene kadar benim için mükemmel çalıştı.

Bir .doc dosyasının yüklenmesi mükemmel bir şekilde çalıştı, ancak bir .pdf'nin yüklenmesi, aşağıdaki kod satırının artık istenen etkiye sahip olmamasına neden oldu ve kullanıcı tarafından uzun bir dokunuşta kopyala / tanımla menüsü yeniden açıldı.

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

Başka bir saç çekmeden sonra bu cevabı burada Johnny Rockex'te buldum ve bir şampiyon gibi çalıştı. PDF dosyalarını görüntülerken Kopyala / Yapıştır olmadan UIWebView

Bu uygulaması kolay, dahice çözüm için kendisine çok teşekkürler !!


2

Benim için, görüntüleri almaya niyetinde NSDatadan UIWebViewtarafındanLongPressGesture .

Ancak Büyüteç ve Kopyala / Yapıştır / Kes her zaman işlevim çalıştırılmadan önce gerçekleşir.

Ve şunu buldum: görüntü açıklamasını buraya girin

Bu, Büyüteç ve Kopyala / Yapıştır / Kes'in yürütmek için 0,5 saniyeye ihtiyaç duyduğu anlamına gelir, bu nedenle işleviniz 0,49 saniyede yürütülebilirse, TAMAMLANDI!

self.longPressPan.minimumPressDuration = 0.3

bu benim için iOS 9 + Xcode 7 GM'de çalışıyor, denediğim diğer yöntemler sadece iOS 7 ve 8'de kullanışlıdır
Kaiyuan Xu

-4

Web görünümü kesme işlevini kullanın

   webView.userInteractionEnabled = false

Benim için çalışıyor

Not: Kullanıcının web görünümüyle tekrar etkileşime girmesini istediğinizde etkileşimi tekrar etkinleştirmeyi unutmayın.


1
Stackoverflow'a hoş geldiniz. Cevap bu eski soruya gerçekten değer katıyor mu? Lütfen Nasıl Cevaplanacağını inceleyin .
dbank

1
Cevabınızın değerini artırmak için cevabınızı genişletmeyi düşünün (bazı küçük kod örnekleri sağlayın). Ayrıca, 'benim için çalışıyor' ifadesini içeren yanıtlar gerçekten güven vermez - yanıtı olduğu gibi sunmak ve ardından birisi yanıtınız hakkında açıklama isterse sorunu gidermek daha iyidir.
Aaron D
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.