【问题标题】:UIWebView without Copy/Paste when displaying PDF files显示 PDF 文件时没有复制/粘贴的 UIWebView
【发布时间】:2012-10-07 10:57:45
【问题描述】:

我尝试通过使用类别并覆盖 canPerformAction 并为复制、剪切和粘贴选择器返回 NO 来禁用 UIWebView 中的复制/粘贴。

当我加载网页或所有其他文档格式(例如 docx、pptx、rtf、txt)时,它按预期工作,但当我将 PDF 文档加载到 UIWebView 时却没有。

似乎有一些不同的机制可以处理 UIWebView 中的 PDF 文档,它处理/响应 Copy 选择器,因此我无法阻止它。

我还尝试禁用 UIWebView 的 UIScrollView 的所有子视图的用户交互,这对于除 PDF 之外的其他文档格式都适用。

谁能帮助弄清楚如何在 UIWebView 中为 PDF 文档禁用复制?

【问题讨论】:

    标签: pdf uiwebview


    【解决方案1】:

    好的,所以我自己也遇到过同样的问题,并且似乎找到了解决方案,即使它是部分的。

    我所做的是使用 UILongPressGestureRecognizer 来禁用可能导致复制/粘贴的长按手势。

    代码:

    UILongPressGestureRecognizer* longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)]; // allocating the UILongPressGestureRecognizer
    
    longPress.allowableMovement=100; // Making sure the allowable movement isn't too narrow
    
    longPress.minimumPressDuration=0.3; // This is important - the duration must be long enough to allow taps but not longer than the period in which the scroll view opens the magnifying glass
    
    longPress.delegate=self; // initialization stuff
    longPress.delaysTouchesBegan=YES;
    longPress.delaysTouchesEnded=YES;
    
    longPress.cancelsTouchesInView=YES; // That's when we tell the gesture recognizer to block the gestures we want 
    
    [webView addGestureRecognizer:longPress]; // Add the gesture recognizer to the view and scroll view then release
    [[webView scrollView] addGestureRecognizer:longPress]; 
    [longPress release];
    

    【讨论】:

    • 好吧,我认为没有其他方法可以处理这个问题。所以这是一个完整的答案,而不是部分的!为此 +1!
    【解决方案2】:

    这个解决方案对我有用:

    方法 1 - 检测自定义长按

    A) 创建 UILongPressGestureRecognser 的子类。

    B) 在子类中包含canBePreventedByGestureRecognizer: 方法,如下所示:

    标题:

    #import <UIKit/UIKit.h> 
    
    @interface CustomLongPress : UILongPressGestureRecognizer
    
    @end    
    

    实施:

    #import "CustomLongPress.h"
    
    @implementation CustomLongPress
    
    - (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer*)preventedGestureRecognizer {
     return NO;
    }
    
    @end
    

    这是您在子类中唯一需要的代码。

    C) 打开包含您的 uiwebview/pdf 阅读器的视图。包括您的子类:#import "CustomLongPress.h",然后将自定义 UILongPressGestureRecognser 添加到您的 UIWebView,如下所示:

    - (void)viewDidLoad
    { 
       [super viewDidLoad];
    
       //Load UIWebView etc
    
       //Add your custom gesture recogniser
       CustomLongPress * longPress = [[CustomLongPress alloc] initWithTarget:self action:@selector(longPressDetected)];
       [pdfWebView addGestureRecognizer:longPress];
    
    }
    

    D) 检测长按并关闭 UIWebView 的 userInteraction 然后再打开:

    -(void)longPressDetected {
    
    NSLog(@"long press detected");
    [pdfWebView setUserInteractionEnabled:NO];
    [pdfWebView setUserInteractionEnabled:YES];
    }
    

    显然,这是因为 UIWebView 使用自己的手势识别器捕获长按,排除您添加的任何其他手势识别器。但是将手势识别器子类化并通过向canBePreventedByGestureRecognizer: 方法返回“NO”来防止它们被排除在外,会覆盖默认行为。

    一旦您可以检测到在 PDF 上的长按,将 userInteraction 关闭然后再打开会阻止 UIWebView 执行其默认行为,即启动“复制/定义”UIMenu,或者,如果长按链接,则启动弹出窗口- 带有“复制”和“打开”操作的操作表。

    方法 2 - 捕捉 UIMenu NSNotification

    或者,如果您只想阻止“复制/定义”UIMenu(但不影响长按),您可以将此行(监听 UIMenuControllerDidShowMenuNotification)添加到您的 ViewDidLoad:

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(menuShown) name:UIMenuControllerDidShowMenuNotification object:nil];
    

    然后添加此方法,使用与上面相同的 userInteraction Off/On 方法:

    -(void)menuShown {
        NSLog(@"menu shown");
        [pdfWebView setUserInteractionEnabled:NO];
        [pdfWebView setUserInteractionEnabled:YES];   
    }
    

    第一种方法取自:https://devforums.apple.com/thread/72521?start=25&tstart=0,第二种方法取自 Stack 上的某个地方,抱歉忘记在哪里了。如果您知道,请提供。

    【讨论】:

    • 如果尝试双击然后长按。有时允许复制。
    【解决方案3】:

    祖巴巴的回答很好。我正在使用 webView 来显示彩色和粗体文本,我遇到了同样的问题。我将您的解决方案放入一个方法中,并在初始化 webView 后立即调用它。我似乎不需要委托。

    self.textView = [[UIWebView alloc] initWithFrame:textFrame];
    [self longPress:self.textView];
    
    - (void)longPress:(UIView *)webView {
    
    UILongPressGestureRecognizer* longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress)]; // allocating the UILongPressGestureRecognizer
    
    longPress.allowableMovement=100; // Making sure the allowable movement isn't too narrow
    longPress.minimumPressDuration=0.3; // This is important - the duration must be long enough to allow taps but not longer than the period in which the scroll view opens the magnifying glass
    
    longPress.delaysTouchesBegan=YES;
    longPress.delaysTouchesEnded=YES;
    
    longPress.cancelsTouchesInView=YES; // That's when we tell the gesture recognizer to block the gestures we want
    
    [webView addGestureRecognizer:longPress]; // Add the gesture recognizer to the view and scroll view then release
    [webView addGestureRecognizer:longPress];
    

    }

    - (void)handleLongPress {
    
    }
    

    【讨论】:

    • 用过。但有几次允许复制。
    【解决方案4】:

    如果有人需要 Zubaba 在 Swift 3 中的回答;

    let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
    longPress.allowableMovement = 100
    longPress.minimumPressDuration = 0.3
    longPress.delegate = self
    longPress.delaysTouchesBegan = true
    longPress.delaysTouchesEnded = true
    longPress.cancelsTouchesInView = true
    yourWebView.addGestureRecognizer(longPress)
    yourWebView.scrollView.addGestureRecognizer(longPress)
    
    
    func handleLongPress() {
         // Show some alert to inform user or do nothing.
    }
    

    【讨论】:

    • 它从第二次开始对我有用。第一次如果我长按它会显示打开/复制操作表,但之后就不会了。你知道解决办法吗?
    • 我刚刚尝试了代码,它按预期工作。你确定你的文件类型是pdf吗?因为对于不同的文件类型有不同的解决方案。如果 fileExtension == "pdf" { disableUIMenuContOpeningForPDFs() } 检查您的文件在 viewDidLoad() 中的扩展名是否像这样
    • 我对 Xamarin 做的事情基本上是一样的,而且在每个 PDF 页面第一次之后我也让它工作。有人解决了第二次问题吗?
    【解决方案5】:

    这是对 Zubaba 在 Swift 3 中的回答的修改,最终帮助我消除了警告。我将分配longPress.delegate = self 更改为longPress.delegate = self as? UIGestureRecognizerDelegate

        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
        longPress.allowableMovement = 100
        longPress.minimumPressDuration = 0.3
        longPress.delegate = self as? UIGestureRecognizerDelegate
        longPress.delaysTouchesBegan = true
        longPress.delaysTouchesEnded = true
        longPress.cancelsTouchesInView = true
        webView.addGestureRecognizer(longPress)
        webView.scrollView.addGestureRecognizer(longPress)
    
        webView.loadRequest(request)
    

    【讨论】:

      【解决方案6】:

      UILongPressGestureRecognizer 位于 UIPDFPageView 中。要访问此视图,请查看“调试”菜单中的视图层次结构,目前您可以在将 pdf 加载到 Web 视图后访问此视图:

      let pdfPageView = myWebView.scrollview?.subviews[0]?.subviews[0]
      

      然后在传递pdfPageView时使用此方法删除长按:

      func removeLongPressFromView(view: UIView){
        if let gestures = view.gestureRecognizers{
          for gesture in gestures{
            if gesture is UILongPressGestureRecognzier{
              view.removeGestureRecognizer(gesture)
            }
          }
        }
      }
      

      【讨论】:

        【解决方案7】:

        寻找 Xamarin.iOS 解决方案。

        var longPressGestureRecognizer = new CustomLongPressGestureRecognizer ((UILongPressGestureRecognizer obj) => 
        {
          Console.WriteLine ("CustomLongPressGestureRecognizer action");
        });
        webView.AddGestureRecognizer (longPressGestureRecognizer);
        

        祖巴巴给出的方法可能是这样的:

        public class ZubabaLongPressGestureRecognizer : UIKit.UILongPressGestureRecognizer
        {
            public ZubabaLongPressGestureRecognizer (Action<UILongPressGestureRecognizer> action)
              : base (action)
            {
                AllowableMovement = 100;
                MinimumPressDuration = 0.3;
                DelaysTouchesBegan = true;
                DelaysTouchesEnded = true;
                CancelsTouchesInView = true;
            }
        }
        

        打开/复制/取消菜单仍然会在每个 PDF 页面首次长时间保存链接时显示。但是,在第一次长按之后,该页面没有正确显示。这取决于 PDF 页面并不能让我相信有可用的解决方案。

        Johnny Rockex 的解决方案可能如下所示:

        public class RockexLongPressGestureRecognizer : UIKit.UILongPressGestureRecognizer
        {
            public RockexLongPressGestureRecognizer(UIKit.UIWebView webView, Action<UILongPressGestureRecognizer> action) :
                base(UserInteractionAction(webView) + action)
            {
        
            }
        
            private static Action<UILongPressGestureRecognizer> UserInteractionAction(UIKit.UIWebView webView)
            {
                return (UILongPressGestureRecognizer obj) =>
                 {
                     webView.UserInteractionEnabled = false;
                     webView.UserInteractionEnabled = true;
                 };
            }
        
            public override bool CanPreventGestureRecognizer(UIGestureRecognizer preventedGestureRecognizer)
            {
                return false;
            }
        }
        

        notificationToken1 = UIMenuController.Notifications.ObserveMenuFrameDidChange (Callback);
        notificationToken2 = NSNotificationCenter.DefaultCenter.AddObserver(UIMenuController.DidShowMenuNotification, Callback);
        

        我无法让他们做任何事情。帮助其他人在 Xamarin.iOS 修复方面做得更好

        【讨论】:

          【解决方案8】:

          1.ios11 iphone6 Object-C无复制/粘贴/lookUp/share

          2.

          viewDidLoad{
              .......
              [self setupExclude];
          }
          
          - (void)setupExclude{
              UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPG)];
              longPress.minimumPressDuration = 0.2;
              [self.webview addGestureRecognizer:longPress];
          
              UITapGestureRecognizer *singleTapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:nil];
              singleTapGesture.numberOfTapsRequired = 1;
              singleTapGesture.numberOfTouchesRequired  = 1;
              [self.webview addGestureRecognizer:singleTapGesture];
          
              UITapGestureRecognizer *doubleTapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(longPG)];
              doubleTapGesture.numberOfTapsRequired = 2;
              doubleTapGesture.numberOfTouchesRequired = 1;
              [self.webview addGestureRecognizer:doubleTapGesture];
              [singleTapGesture requireGestureRecognizerToFail:doubleTapGesture];
          }
          - (BOOL)canPerformAction:(SEL)action withSender:(id)sender{
              BOOL res = [super canPerformAction:action withSender:sender];
              UIMenuController.sharedMenuController.menuVisible = NO;
              self.webview.userInteractionEnabled = NO;
              self.webview.userInteractionEnabled = YES;
              return res;
          }
          - (void)longPG{
              UIMenuController.sharedMenuController.menuVisible = NO;
              self.webview.userInteractionEnabled = NO;
              self.webview.userInteractionEnabled = YES;
          }
          

          3。完成!

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-05-13
            • 1970-01-01
            • 2012-07-02
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多