#swift #pdfkit
#swift #pdfkit
Вопрос:
Я пытаюсь показать загрузку, пока PDF-файл еще не был показан на экране. Проблема в том, что моя загрузка всегда останавливается до того, как документ уже отрисован, иногда это не может занять 2 или 3 секунды, и мне нужно знать, когда PDF уже отрисован, чтобы остановить activyIndicator . Возможно ЛИ ЭТО с помощью PDFKIT? Мой код:
class PDFViewController: URLSessionDownloadDelegate {
@IBOutlet weak var pdfView: PDFView!
var pdfDocument: PDFDocument!
override func viewDidLoad() {
super.viewDidLoad()
setupPDFView()
setupNavigationBar()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.startLoading()
}
override func viewDidAppear(_ animated: Bool) {
super.viewWillAppear(animated)
loadPDF()
}
private func loadPDF() {
DispatchQueue.main.async {
guard let url = URL(string: self.viewModel.pdfURL) else {
self.showAlert(with: self.viewModel.strings.invalidInvoice)
return
}
let urlSession = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue())
let downloadTask = urlSession.downloadTask(with: url)
downloadTask.resume()
}
}
private func setupPDFView() {
self.pdfView.displayMode = .singlePageContinuous
self.pdfView.autoScales = true
}
func startLoading() {
guard let window = UIApplication.shared.keyWindow,
!window.subviews.contains(where: { $0 is LoadingView }) else { return }
let loadingView = LoadingView(frame: window.bounds)
window.addSubview(loadingView)
Thread.performUIUpdate {
loadingView.startAnimation()
}
}
func stopLoading() {
guard let window = UIApplication.shared.keyWindow,
let view = window.subviews.first(where: { $0 is LoadingView }),
let loadingView = view as? LoadingView else { return }
Thread.performUIUpdate {
loadingView.stopAnimation()
loadingView.removeFromSuperview()
}
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
DispatchQueue.main.async {
self.pdfDocument = PDFDocument(url: location)
if let pdfDocument = self.pdfDocument {
self.pdfView.document = pdfDocument
}
self?.stopLoading()
}
}
}
Комментарии:
1. Пожалуйста, не публикуйте неполный код. Если
self.startLoading()
это уместно, покажите определениеstartLoading
. Не оставляйте нас гадать, что он делает.2. мой плохой. Я только что добавил код
3. Хорошо, я понимаю. Итак, где именно задержка в 2 или 3 секунды? (Я немного удивлен, что ваш код вообще работает, потому что вы недостаточно быстро загружаете загруженный документ, но это может быть другой проблемой.)
4. прямо сейчас я использую URLSession, чтобы остановить LoadingView. Когда я вызываю self?.stopLoading, PDF-файл уже загружен, и PDFView.document уже установлен. Но я вызываю stopLoading, загрузка останавливается… и pdf еще не отображается на экране. Иногда для фактического отображения требуется 2 или 3 секунды, иногда он отображается точно при вызове stopLoading . Кстати, я забыл добавить определение остановки загрузки, я добавляю, но это в основном останавливает просмотр загрузки.
Ответ №1:
Это кажется действительно плохой идеей:
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
DispatchQueue.main.async {
self.pdfDocument = PDFDocument(url: location)
Проблема в том, что, когда вы выходите из текущего потока и запускается асинхронный код, метод завершается, и временный документ at location
может быть уничтожен. Я бы предложил написать так:
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
let pdf = PDFDocument(url: location)
DispatchQueue.main.async {
self.pdfDocument = pdf
Я не говорю, что это решит вашу проблему, но это кажется намного менее опасным, чем то, что вы делаете.
Что касается вашей реальной проблемы, я бы предложил зарегистрироваться для получения уведомления, подобного этому, и посмотреть, придет ли оно в нужный момент.
Ответ №2:
Вы должны наблюдать за уведомлением PDFViewVisiblePagesChanged, чтобы узнать, когда страницы PDFView видны, добавьте свой код в метод.
NotificationCenter.default.addObserver(self, selector: #selector(pdfViewVisiblePagesChanged(sender:)), name: .PDFViewVisiblePagesChanged, object: nil)
@objc func pdfViewVisiblePagesChanged(sender: Notification) {
//Add your code here
}