Отображение PDFDocument в PDFView позволяет пользователю выбирать части документа и выполнять действия, например, «Копировать» с выбором. Как можно отключить выбор в PDFView, сохраняя при этом возможность для пользователя увеличивать и уменьшать масштаб и прокручивать PDF?

Сам PDFView, похоже, не предлагает такого свойства, как и PDFViewDelegate.

9
chriswillow 4 Мар 2018 в 22:28

5 ответов

Лучший ответ

Вы должны создать подкласс 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)
    }

}
7
AamirR 4 Мар 2018 в 20:02

Для iOS 13 вышеуказанное решение больше не работает. Похоже, они изменили внутреннюю реализацию PDFView и, в частности, способ настройки распознавателей жестов. Я думаю, что вообще не рекомендуется делать такие вещи, но все же это можно сделать без использования какого-либо внутреннего API, вот как:

1) Рекурсивно собрать все подпредставления PDFView (см. Ниже вспомогательную функцию, чтобы сделать это)

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
}

Я вызываю приведенный выше код из метода viewDidLoad содержащего контроллера представления.

Я еще не нашел хороший способ превратить это в подкласс PDFView, который был бы предпочтительным способом для повторного использования и мог бы просто быть дополнением к вышеупомянутому NonSelectablePDFView. До сих пор я пробовал переопределить didAddSubview и добавить вышеуказанный код после вызова super, но это не сработало, как ожидалось. Кажется, что распознаватели жестов добавляются только на более позднем этапе, поэтому следующий шаг - выяснить, когда это произойдет, и есть ли у подкласса способ вызвать какой-то пользовательский код после того, как это произошло.

2
julsh 1 Окт 2019 в 14:43

Просто нужно сделать, это автоматически очистит выбор, и пользователь больше не будет долго нажимать на текст 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()
2
Darshit Mendapara 24 Фев 2020 в 13:44

Вы должны заметить, что этого недостаточно, чтобы отключить выбор текста, так как есть UITapAndHalfRecognizer - очевидно, частный класс Apple - который также создает выборки.

Он прикреплен к PDFDocumentView, который является еще одной частной деталью реализации PDFView, и которую вы не можете заменить собственной реализацией класса.

0
Klaus Busse 17 Янв 2020 в 11:52

В Swift 5 и iOS 12.3 вы можете решить свою проблему, переопределив {{X0} } метод и 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
    }

}
2
Imanou Petit 3 Июл 2019 в 12:41