如何在 PDFView 中禁用选择?
How can selection be disabled in PDFView?
在 PDFView
中显示 PDFDocument
允许用户 select 部分文档并执行操作,例如"copy" 与 select 离子。
selection 如何在 PDFView 中禁用,同时保留用户放大和缩小以及在 PDF 中滚动的可能性?
PDFView
本身似乎没有提供这样的 属性 也没有 PDFViewDelegate
.
您必须子类化 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)
}
}
使用 Swift 5 和 iOS 12.3,您可以通过覆盖 PDFView
子类中的 addGestureRecognizer(_:)
method and 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,上述解决方案不再有效。看起来他们已经更改了 PDFView
的内部实现,特别是手势识别器的设置方式。我认为通常不鼓励做这种事情,但它仍然可以在不使用任何内部 API 的情况下完成,方法如下:
1) 递归收集 PDFView
的所有子视图(请参阅下面的辅助函数来执行此操作)
let allSubviews = pdfView.allSubViewsOf(type: UIView.self)
2) 迭代它们并停用任何 UILongPressGestureRecognizer
s:
for gestureRec in allSubviews.compactMap({ [=11=].gestureRecognizers }).flatMap({ [=11=] }) {
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: [=12=]) }
}
getSubview(view: self)
return all
}
我从包含视图控制器的 viewDidLoad
方法调用上面的代码。
我还没有找到将其放入 PDFView
的子类的好方法,这将是可重用性的首选方法,并且可能只是对上述 NonSelectablePDFView
的补充。到目前为止,我尝试过覆盖 didAddSubview
并在调用 super
之后添加上面的代码,但这并没有按预期工作。似乎手势识别器只是在稍后的步骤中添加,所以弄清楚什么时候添加,以及在这发生之后子类是否有办法调用一些自定义代码将是这里的下一步。
您应该注意,这不足以禁用文本选择,因为还有一个 UITapAndHalfRecognizer – 显然是一个私人 Apple class – 也创建选择。
它附加到 PDFDocumentView,这是 PDFView 的另一个私有实现细节,您不能用自己的 class 实现替换它。
只需要做的就是自动清除选择,用户将不再长按 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)
}
}
下面2行需要在canPerformAction()中添加
self.currentSelection = nil
self.clearSelection()
在 PDFView
中显示 PDFDocument
允许用户 select 部分文档并执行操作,例如"copy" 与 select 离子。
selection 如何在 PDFView 中禁用,同时保留用户放大和缩小以及在 PDF 中滚动的可能性?
PDFView
本身似乎没有提供这样的 属性 也没有 PDFViewDelegate
.
您必须子类化 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)
}
}
使用 Swift 5 和 iOS 12.3,您可以通过覆盖 PDFView
子类中的 addGestureRecognizer(_:)
method and 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,上述解决方案不再有效。看起来他们已经更改了 PDFView
的内部实现,特别是手势识别器的设置方式。我认为通常不鼓励做这种事情,但它仍然可以在不使用任何内部 API 的情况下完成,方法如下:
1) 递归收集 PDFView
的所有子视图(请参阅下面的辅助函数来执行此操作)
let allSubviews = pdfView.allSubViewsOf(type: UIView.self)
2) 迭代它们并停用任何 UILongPressGestureRecognizer
s:
for gestureRec in allSubviews.compactMap({ [=11=].gestureRecognizers }).flatMap({ [=11=] }) {
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: [=12=]) }
}
getSubview(view: self)
return all
}
我从包含视图控制器的 viewDidLoad
方法调用上面的代码。
我还没有找到将其放入 PDFView
的子类的好方法,这将是可重用性的首选方法,并且可能只是对上述 NonSelectablePDFView
的补充。到目前为止,我尝试过覆盖 didAddSubview
并在调用 super
之后添加上面的代码,但这并没有按预期工作。似乎手势识别器只是在稍后的步骤中添加,所以弄清楚什么时候添加,以及在这发生之后子类是否有办法调用一些自定义代码将是这里的下一步。
您应该注意,这不足以禁用文本选择,因为还有一个 UITapAndHalfRecognizer – 显然是一个私人 Apple class – 也创建选择。
它附加到 PDFDocumentView,这是 PDFView 的另一个私有实现细节,您不能用自己的 class 实现替换它。
只需要做的就是自动清除选择,用户将不再长按 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)
}
}
下面2行需要在canPerformAction()中添加
self.currentSelection = nil
self.clearSelection()