ปิดการใช้งานการเลือกผู้ใช้ใน UIWebView


121

ฉันมีแอปที่ฉันโหลดเนื้อหาไปยังไฟล์ UIWebViewและนำเสนอสิ่งนี้ ฉันไม่สามารถปิดการใช้งานการโต้ตอบของผู้ใช้ได้อย่างสมบูรณ์เพราะฉันต้องการให้ผู้ใช้สามารถคลิกลิงก์ได้ ฉันต้องปิดการใช้งานการเลือกผู้ใช้ ฉันพบที่ไหนสักแห่งใน Internets ที่คุณสามารถใช้ได้:

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

1
ขยายUIWebViewโดยใช้หมวดหมู่
Deepak Danduprolu

4
Engin ตัวแรกทำงานใน Mobile Safari, iOS 4.3.1 แต่ WrightCS ลืมเพิ่มตัวเลือก หากต้องการใช้กับทุกองค์ประกอบให้ใช้เครื่องหมายดอกจันเช่น * {/ * css ไปที่นี่ * /}
fisherwebdev

1
การเพิ่มสไตล์ทำงานได้อย่างสมบูรณ์แบบในการลบเมนูที่ปรากฏขึ้นเมื่อมีการแตะบนลิงก์ภายในแอป PhoneGap ของฉัน
spatical

7
canPerformActionไม่ปิดใช้งานเมนูตัดคัดลอกวาง และเลือกเลือกเมนูทั้งหมด จะแก้ไขได้อย่างไร? -webkit-touch-calloutและremoveAllRangesทำลายอินพุตของผู้ใช้ ไม่สามารถใช้วิธีการที่ให้มาทั้งหมด :(
Dmitry

4
ปัญหาในการวางลักษณะที่ไม่เลือกเหล่านี้ใน*ขอบเขตส่วนกลางคือหยุดการป้อนข้อมูลของผู้ใช้ในเว็บฟอร์ม ฉันพบว่าฉันได้ผลลัพธ์ที่ดีกว่าโดยวางไว้ในbodyแท็กแทน
David Douglas

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 Perfect Guy!
ΩlostA

25

ฉันใช้เทคนิคนี้ในเว็บแอปสำหรับ Android / iPhone (มาพร้อมกับ Trigger.IO) และพบว่ามันใช้ได้เฉพาะกับไวยากรณ์การผูกมัดสำหรับ: not () pseudo-class,:

*: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;}แต่นั่นไม่ได้เป็นเคล็ดลับสำหรับฉัน ขอบคุณ!
Mark Rummel

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

9

ฉันไม่แน่ใจว่าการตั้งค่าเสร็จสิ้นอย่างไร แต่ทำไมคุณไม่เพียงแค่ล้าง pasteBoard เมื่อเรียก viewWillDisappear อาจมีบางอย่างเช่นใน appDelegate.m ของคุณ:

[UIPasteboard generalPasteboard].string = nil;

สิ่งนี้จะช่วยให้แน่ใจว่าข้อมูลใดก็ตามที่ผู้ใช้อาจคัดลอกพวกเขาจะไม่สามารถวางข้อมูลนั้นนอกแอปได้

นอกจากนี้เช่น Engin กล่าวว่าคุณสามารถแทนที่เมธอด canPerformSelector ในคลาสคอนโทรลเลอร์ที่มี uiwebview


1
นี่เป็นหนึ่งในวิธีแก้ปัญหาที่ดีที่สุด สามารถตั้งค่าได้ใน - (void) applicationDidEnterBackground: (UIApplication *) ตัวจัดการเหตุการณ์ของแอปพลิเคชัน และสิ่งนี้ทำให้มั่นใจได้ว่าจะไม่มีข้อมูลหลุดออกจากแอพ
Krishnan

@Krishan คุณแน่ใจ 100% หรือไม่ว่าจะหยุดภาพหน้าจอด้วย
Norman H

ฉันชอบโซลูชันนี้ แต่เนื่องจากมันยังคงอยู่บน Pasteboard ในขณะที่แอปพลิเคชันทำงานอยู่แอปพลิเคชันอื่น (ที่เป็นอันตราย) ที่ทำงานในเธรดพื้นหลังสามารถเข้าถึง Pasteboard ทั่วไปได้ในขณะที่มีข้อมูลอยู่
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 สัปดาห์! คำตอบอื่น ๆ ทั้งหมดไม่ถูกต้องหากคุณต้องการบันทึกเหตุการณ์ของเมาส์และการป้อนข้อมูลของผู้ใช้ในหลาย ๆ หน้า

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

หลังจากการดึงผมอีกครั้งฉันพบคำตอบนี้ที่นี่โดย Johnny Rockex และมันก็ทำงานได้เหมือนแชมป์ UIWebView โดยไม่ต้องคัดลอก / วางเมื่อแสดงไฟล์ PDF

ขอบคุณมากสำหรับเขาสำหรับโซลูชันอัจฉริยะที่ใช้งานง่ายนี้ !!


2

สำหรับฉันฉันตั้งใจจะดึงภาพNSDataจากUIWebViewโดยLongPressGestureโดย

แต่แว่นขยายและ Copy / Paste / Cut จะเกิดขึ้นก่อนที่ func จะดำเนินการเสมอ

และฉันพบสิ่งนี้: ใส่คำอธิบายภาพที่นี่

หมายความว่าแว่นขยายและ Copy / Paste / Cut ต้องใช้ 0.5 วินาทีในการดำเนินการดังนั้นหาก func ของคุณสามารถดำเนินการได้ใน 0.49 วินาทีเสร็จสิ้น!

self.longPressPan.minimumPressDuration = 0.3

สิ่งนี้ใช้ได้กับฉันใน iOS 9 + Xcode 7 GM วิธีอื่น ๆ ที่ฉันลองมีประโยชน์ใน iOS 7 และ 8 เท่านั้น
Kaiyuan Xu

-4

ใช้ฟังก์ชัน interection มุมมองเว็บ

   webView.userInteractionEnabled = false

มันใช้ได้กับฉัน

PS: อย่าลืมเปิดใช้งานการโต้ตอบกลับเมื่อคุณต้องการให้ผู้ใช้โต้ตอบกับ webview ได้อีกครั้ง


1
ยินดีต้อนรับสู่ stackoverflow คำตอบช่วยเพิ่มคุณค่าให้กับคำถามเก่า ๆ นี้จริงหรือ? โปรดตรวจสอบวิธีการตอบ
dbank

1
ลองขยายคำตอบของคุณ (ให้ตัวอย่างโค้ดขนาดเล็ก) เพื่อเพิ่มมูลค่าของคำตอบของคุณ นอกจากนี้คำตอบที่มี 'มันได้ผลสำหรับฉัน' ไม่ได้สร้างความมั่นใจอย่างแท้จริง - ดีกว่าที่จะนำเสนอคำตอบตามที่เป็นอยู่จากนั้นจึงแก้ไขปัญหาหากมีคนขอคำชี้แจงเกี่ยวกับคำตอบของคุณ
Aaron D
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.