【问题标题】:How can selection be disabled in PDFView?如何在 PDFView 中禁用选择?
【发布时间】:2018-08-12 11:04:13
【问题描述】:

PDFView 中显示PDFDocument 允许用户选择文档的各个部分并执行操作,例如“复制”与选择。 如何在 PDFView 中禁用选择,同时保留用户在 PDF 中放大和缩小和滚动的可能性?

PDFView 本身似乎没有提供这样的属性,PDFViewDelegate 也没有。

【问题讨论】:

    标签: ios swift pdfkit pdfview


    【解决方案1】:

    你必须继承 PDFView,像这样:

    class MyPDFView: PDFView {
    
        override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
            return false
        }
    
        override func addGestureRecognizer(_ gestureRecognizer: UIGestureRecognizer) {
            if gestureRecognizer is UILongPressGestureRecognizer {
                gestureRecognizer.isEnabled = false
            }
    
            super.addGestureRecognizer(gestureRecognizer)
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      对于 iOS 13,上述解决方案不再有效。看起来他们已经改变了PDFView 的内部实现,特别是手势识别器的设置方式。我认为通常不鼓励这样做,但仍然可以在不使用任何内部 API 的情况下完成,方法如下:

      1) 递归收集PDFView 的所有子视图(请参阅下面的帮助函数)

      let allSubviews = pdfView.allSubViewsOf(type: UIView.self)
      

      2) 遍历它们并停用任何UILongPressGestureRecognizers:

      for gestureRec in allSubviews.compactMap({ $0.gestureRecognizers }).flatMap({ $0 }) {
          if gestureRec is UILongPressGestureRecognizer {
              gestureRec.isEnabled = false
          }
      }
      

      帮助函数递归获取给定类型的所有子视图:

      func allSubViewsOf<T: UIView>(type: T.Type) -> [T] {
          var all: [T] = []
          func getSubview(view: UIView) {
              if let aView = view as? T {
                  all.append(aView)
              }
              guard view.subviews.count > 0 else { return }
              view.subviews.forEach{ getSubview(view: $0) }
          }
          getSubview(view: self)
          return all
      }
      

      我从包含视图控制器的viewDidLoad 方法调用上述代码。

      我还没有找到一个很好的方法来将它放入PDFView 的子类中,这将是可重用性的首选方式,并且可能只是上述NonSelectablePDFView 的补充。到目前为止,我尝试的是覆盖didAddSubview 并在调用super 之后添加上面的代码,但这并没有按预期工作。手势识别器似乎只是在稍后的步骤中添加,因此确定何时添加,以及子类是否有办法在发生这种情况后调用一些自定义代码将是下一步。

      【讨论】:

      • 这会禁用长按编辑,但不会禁用双击并按住。将 type(of:gestureRec).description() == "UITapAndAHalfRecognizer" 添加到上面 2) 中的 if 中。
      【解决方案3】:

      只需要做的是它会自动清除选择,用户将不再长按 PDF 文本。

      class MyPDFView: PDFView {
      
          override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
              self.currentSelection = nil
              self.clearSelection()
      
              return false
          }
      
          override func addGestureRecognizer(_ gestureRecognizer: UIGestureRecognizer) {
              if gestureRecognizer is UILongPressGestureRecognizer {
                  gestureRecognizer.isEnabled = false
              }
      
              super.addGestureRecognizer(gestureRecognizer)
          }
      
      }
      

      下面两行需要添加到canPerformAction()中

      self.currentSelection = nil
      self.clearSelection()
      

      【讨论】:

        【解决方案4】:

        使用 Swift 5 和 iOS 12.3,您可以通过在 PDFView 子类中覆盖 addGestureRecognizer(_:) 方法和 canPerformAction(_:withSender:) 方法来解决您的问题。

        import UIKit
        import PDFKit
        
        class NonSelectablePDFView: PDFView {
        
            override func addGestureRecognizer(_ gestureRecognizer: UIGestureRecognizer) {
                (gestureRecognizer as? UILongPressGestureRecognizer)?.isEnabled = false
                super.addGestureRecognizer(gestureRecognizer)
            }
        
            override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
                return false
            }
        
        }
        

        作为之前实现的替代方案,您可以在初始化程序中简单地将 UILongPressGestureRecognizer isEnabled 属性切换为 false

        import UIKit
        import PDFKit
        
        class NonSelectablePDFView: PDFView {
        
            override init(frame: CGRect) {
                super.init(frame: frame)
        
                if let gestureRecognizers = gestureRecognizers {
                    for gestureRecognizer in gestureRecognizers where gestureRecognizer is UILongPressGestureRecognizer {
                        gestureRecognizer.isEnabled = false
                    }
                }
            }
        
            required init?(coder aDecoder: NSCoder) {
                fatalError("init(coder:) has not been implemented")
            }
        
            override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
                return false
            }
        
        }
        

        【讨论】:

        • 看起来这个答案在 iOS13 中不再起作用,Apple 确实改变了一些东西,即使这个代码仍然是选定的文本! ,在 iOS12 及以下版本运行良好!
        【解决方案5】:

        您应该注意,这不足以禁用文本选择,因为还有一个 UITapAndHalfRecognizer - 显然是一个私有 Apple 类 - 也可以创建选择。

        它附加到 PDFDocumentView,这是 PDFView 的另一个私有实现细节,您不能用自己的类实现替换它。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-07-01
          • 1970-01-01
          • 2020-02-14
          • 1970-01-01
          • 1970-01-01
          • 2018-03-31
          • 1970-01-01
          相关资源
          最近更新 更多