9

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

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

4

5 回答 5

7

您必须将 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)
    }

}
于 2018-03-04T20:02:01.423 回答
4

对于 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
    }
}

Helper func 递归获取给定类型的所有子视图:

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,但这并没有按预期工作。手势识别器似乎只是在稍后的步骤中添加,因此确定何时添加,以及子类是否有办法在发生这种情况后调用一些自定义代码将是下一步。

于 2019-10-01T14:43:42.083 回答
4

只需要做的是它会自动清除选择,用户将不再长按 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()
于 2020-02-24T13:44:56.750 回答
2

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

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
    }

}
于 2018-03-11T21:34:03.863 回答
0

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

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

于 2020-01-17T11:52:56.877 回答