Swift PDFKit:与 PDFView.currentDestination 和 PDFView.go 的行为不一致(到目的地:PDFDestination)

Swift PDFKit: Inconsistent behaviour with PDFView.currentDestination and PDFView.go(to destination: PDFDestination)

注意:问题暂无解决;标记的答案提供了一个很好的解决方法 - 它可以在应用程序仍处于打开状态时工作。 仍然欢迎回答!

背景

我目前正在开发一个包含全屏 PDFView 的应用程序,我希望程序在关闭视图之前记住文档中的位置,以便用户可以从他们所在的位置开始已经离开了。

实施

应用程序的简化版本可以理解为使用 PDFKit.PDFView 的 PDF 查看器。情节提要由连接到 PDFView class、DocumentView(符合 UIViewController)的 UIView 组成。视图通过以下过程初始化:

viewDidLoad中:

let PDF: PDFDocument = GetPDFFromServer()
DocumentView.document = PDF!
DocumentView.autoScales = true
... (other settings)

// Set PDF Destination
let Destination: PDFDestination = GetStoredDestination()
// Code with issues
DocumentView.go(to: Destination)

viewWillDisappear中:

StoreDestination(DocumentView.currentDestination)

问题与测试

我意识到代码没有按预期工作;视图没有 return 到它以前的位置。

通过调试,我意识到这可能是由于DocumentView.go(to destination: PDFDestination)DocumentView.currentDestination的行为不一致造成的。

为保证不是存储位置时出错引入bug,使用以下代码验证问题,多页文档:

viewDidLoad

Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { _ in
    DispatchQueue.main.async {
    
self.DocumentView.go(to:self.DocumentView.currentDestination!)
    }

})

预期和观察到的行为

预期:文档的位置不应更改 - 代码每 1 秒转到其当前目的地,这应该没有任何影响。因为“currentDestination”应该是“文档的当前目的地,根据文档”)

观察到:执行后,页面会自动向下滚动一个固定的偏移量。

在 iPadOS 14.5 模拟器和 iPadOS 15 iPad Air(第 4 代)上观察到相同的结果。

可能出了什么问题?

如果有人能提供帮助,那就太好了。

干杯, 林肯

这个问题最初发表在 Apple Developer Forum 一个多星期前;一个多星期都没有听到任何回应,所以我想我可以在 Whosebug 上试试运气 <3

我针对这种情况尝试了 PDFView.go(),我设法让它在某些情况下工作,但发现它在某些其他情况下失败,例如缩放文档、改变方向。

所以回到你想要实现的目标,

I'm currently developing an app that consists of a full-screen PDFView, and I want the program to remember the position in the document before the view is dismissed so the user can pick up where they've left.

这可以通过不同的方法来完成。使用这种方法,您需要始终保留对您创建的 PDFView 的引用。如果之前的 pdf 需要再次加载,那么您将 PDFView 实例原样传递给 viewController 。否则,您将新的 pdf 加载到 PDFView 实例并将其传递给 viewController.

DocumentViewController 在初始化时得到 PDFView

import UIKit
import PDFKit

protocol DocumentViewControllerDelegate: AnyObject {
    func needsContinuePDF(continuePDF: Bool)
}

class DocumentViewController: UIViewController {
    var pdfView: PDFView!
    weak var delegate: DocumentViewControllerDelegate!
    
    init(pdfView: PDFView, delegate: DocumentViewControllerDelegate){
        self.pdfView = pdfView
        self.delegate = delegate
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func loadView() {
        super.loadView()
        self.view.backgroundColor = .white
        view.addSubview(pdfView)
        NSLayoutConstraint.activate([
            pdfView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            pdfView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
            pdfView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            pdfView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
        ])
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        delegate.needsContinuePDF(continuePDF: true)
    }
}

您可以像下面这样初始化 DocumentViewControllerMainViewController 负责初始化 PDFView

import UIKit
import PDFKit

class MainViewController: UIViewController {
    var pdfView: PDFView = PDFView()
    var continuePreviousPDF = false
    
    let button = UIButton(frame: .zero)
    
    override func loadView() {
        super.loadView()
        
        button.setTitle("View PDF", for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.backgroundColor = .systemBlue
        button.addTarget(self, action: #selector(openDocumentView(_:)), for: .touchUpInside)
        self.view.backgroundColor = .systemGray5
        self.view.addSubview(button)
        button.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            button.widthAnchor.constraint(equalToConstant: 100),
            button.heightAnchor.constraint(equalToConstant: 50),
            button.centerXAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.centerXAnchor),
            button.centerYAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.centerYAnchor),
        ])
    }
    
    @objc func openDocumentView(_ sender: UIButton) {
        //open a nee PDF if not continue previous one
        if !self.continuePreviousPDF {
            pdfView.autoScales = true
            pdfView.displayMode = .singlePageContinuous
            pdfView.translatesAutoresizingMaskIntoConstraints = false
            
            guard let path = Bundle.main.url(forResource: "sample copy", withExtension: "pdf") else { return }

            if let document = PDFDocument(url: path) {
                pdfView.document = document
            }
        }
        
        let documentViewController = DocumentViewController(pdfView: pdfView, delegate: self)
        self.present(documentViewController, animated: true, completion: nil)
    }
}

extension MainViewController: DocumentViewControllerDelegate {
    func needsContinuePDF(continuePDF: Bool) {
        self.continuePreviousPDF = continuePDF
    }
}