如何在PDFView中禁用选择?

时间:2018-03-04 19:28:33

标签: ios swift pdfkit pdfview

PDFDocument中显示PDFView,用户可以选择部分文档并执行操作,例如"拷贝"随着选择。 如何在PDFView中禁用选择,同时保留用户放大和缩小以及滚动PDF的可能性?

PDFView本身似乎不提供此类属性,PDFViewDelegate也没有。

5 个答案:

答案 0 :(得分:4)

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

}

答案 1 :(得分: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()

答案 2 :(得分:2)

您可以通过覆盖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
    }

}

答案 3 :(得分:2)

对于iOS 13,以上解决方案不再起作用。看来他们已经更改了PDFView的内部实现,尤其是姿势识别器的设置方式。我认为通常不建议这样做,但是仍然可以在不使用任何内部API的情况下完成操作,方法如下:

1)递归地收集PDFView的所有子视图(有关此功能,请参见下面的辅助函数)

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

2)遍历它们并停用所有UILongPressGestureRecognizer

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

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

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

答案 4 :(得分:0)

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

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