let allSubviews = pdfView.allSubViewsOf(type: UIView.self)
2)迭代它们并停用任何UILongPressGestureRecognizer s:
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
}
import UIKit
import PDFKit
extension UIViewController {
func recursivelyDisableSelection(view: UIView) {
// Get all recognizers for the PDFView's subviews. Here we are ignoring the recognizers for the PDFView itself, since we know from testing that not the reason for the mess.
for rec in view.subviews.compactMap({$0.gestureRecognizers}).flatMap({$0}) {
// UITapAndAHalfRecognizer is for a gesture like "tap first, then tap again and drag", this gesture also enable's text selection
if rec is UILongPressGestureRecognizer || type(of: rec).description() == "UITapAndAHalfRecognizer" {
rec.isEnabled = false
}
}
// For all subviews, if they do have subview in itself, disable the above 2 gestures as well.
for view in view.subviews {
if !view.subviews.isEmpty {
recursivelyDisableSelection(view: view)
}
}
}
}
6条答案
按热度按时间siv3szwd1#
你必须子类化PDFView,如下所示:
2ledvvac2#
只需要做的是它将自动清除选择和用户将不再长按PDF文本。
这下面2行需要在canPerformAction()中添加
zbq4xfa03#
对于iOS 13,上述解决方案不再有效。看起来他们已经改变了
PDFView
的内部实现,特别是手势识别器的设置方式。我认为通常不鼓励做这种事情,但它仍然可以在不使用任何内部API的情况下完成,下面是如何做到的:1)递归收集
PDFView
的所有子视图(参见下面的helper函数)2)迭代它们并停用任何
UILongPressGestureRecognizer
s:帮助函数可以递归地获取给定类型的所有子视图:
我从包含视图控制器的
viewDidLoad
方法调用上面的代码。我还没有找到一个好的方法来将其工作到
PDFView
的子类中,这将是可重用性的首选方法,并且可能只是对上述NonSelectablePDFView
的补充。到目前为止,我所尝试的是覆盖didAddSubview
并在调用super
之后添加上述代码,但这并没有像预期的那样工作。看起来手势识别器只是在后面的步骤中添加的,所以弄清楚这是什么时候,以及是否有一种方法让子类在发生这种情况后调用一些自定义代码将是这里的下一步。o2rvlv0m4#
在Swift 5和iOS 12.3中,你可以通过覆盖
PDFView
子类中的addGestureRecognizer(_:)
方法和canPerformAction(_:withSender:)
方法来解决这个问题。作为前面实现的替代方案,您可以简单地在初始化器中将
UILongPressGestureRecognizer
isEnabled
属性切换为false
。svmlkihl5#
你应该注意到,这不足以禁用文本选择,因为还有一个UITapAndHalfRecognizer--显然是一个私有的Apple类--它也会创建选择。
它被附加到PDFDocumentView,PDFDocumentView是PDFView的另一个私有实现细节,并且您不能用自己的类实现替换它。
9o685dep6#
在我的测试中,双击和“点击然后拖动”不会在iOS16上启用选择,但对于iOS13它会,所以这里是:
1.扩展
UIViewController
,添加一个函数来禁用文本选择。我把它放在UIViewController
的扩展中,所以在调用它的时候,我不需要调用pdfView. recursivelyDisableSelection(view: pdfView)
,只要调用recursivelyDisableSelection(view: pdfView)
就好了。1.当调用函数时,传递
PDFView
的示例,你想禁用文本选择。注意:它应该在PDFView的文档设置之后调用,否则它将无法工作。1.警告:如果您为PDFView启用了usePageViewController(),则在滚动以更改当前页面时,似乎会再次添加手势。一个合理的想法是为
PDFViewPageChanged
消息添加一个观察者,我试过了,它只在某些时候有效。一个更好的监听通知消息是PDFViewVisiblePagesChanged
,这样它总是工作的。同样,观察者应该在PDFView的文档设置好之后添加,否则它将无法工作。所以如果你像我一样使用pageViewController,你应该在两个地方调用它:每次设置文档后,此选项将禁用第一个PDFPage的选择,
PDFViewVisiblePagesChanged
通知中的另一个,用于后续页面滚动。稍后在视图控制器中,定义目标c Package 器函数: