简体   繁体   中英

PDFKit open last read page in a PDF file

So I am using PDFKit to display a PDF and and save/open the last read page. Here's my code. Problem is, the last open page is always 2-4 pages ahead of the one that's actually saved in user defaults. I am not sure what's wrong here.

Ignore the the code with the WebView for iOS versions below 11.

func readBook() {

    if let oldBookView = self.view.viewWithTag(3) {
        oldBookView.removeFromSuperview()
        // This removes the old book view when the user chooses a new book language
    }

    if #available(iOS 11.0, *) {
        let pdfView: PDFView = PDFView()
        let path = BookManager.getBookPath(bookLanguageCode: book.bookLanguageCode)
        let url = URL(fileURLWithPath: path)
        if let pdfDocument = PDFDocument(url: url) {
            pdfView.displayMode = .singlePageContinuous
            pdfView.autoScales = true
            pdfView.document = pdfDocument
            pdfView.tag = 3 // I assigned a tag to this view so that later on I can easily find and remove it when the user chooses a new book language
            let lastReadPage = getLastReadPage()

            if let page = pdfDocument.page(at: lastReadPage) {
                pdfView.go(to: page)
                // Subscribe to notifications so the last read page can be saved
                // Must subscribe after displaying the last read page or else, the first page will be displayed instead
                NotificationCenter.default.addObserver(self, selector: #selector(self.saveLastReadPage),name: .PDFViewPageChanged, object: nil)
            }
        }

        self.containerView.addSubview(pdfView)
        setConstraints(view: pdfView)
        addTapGesture(view: pdfView)
    } else {
        let path = BookManager.getBookPath(bookLanguageCode: book.bookLanguageCode)
        let url = URL(fileURLWithPath: path)
        let webView: WKWebView = WKWebView()
        webView.loadFileURL(url, allowingReadAccessTo: url)
        webView.tag = 3 // I assigned a tag to this view so that later on I can easily find and remove it when the user chooses a new book language

        self.containerView.addSubview(webView)
        setConstraints(view: webView)
        addTapGesture(view: webView)
    }
}

private func getLastReadPage() -> Int {
    let readPagesDictionary: [String:Int] = DataManager.UserDefaultsManager.value(for: .lastReadPage)
    let bookLanguage = book.bookLanguageCode
    let lastReadPage = readPagesDictionary[bookLanguage]

    return lastReadPage!
}

@available(iOS 11.0, *)
@objc private func saveLastReadPage(notification: Notification) {
    let pdfView = notification.object as! PDFView
    var page = pdfView.currentDestination?.page?.pageRef?.pageNumber
    let bookLanguage = book.bookLanguageCode
    var readPageDict: [String:Int] = DataManager.UserDefaultsManager.value(for: .lastReadPage)
    readPageDict.updateValue(page!, forKey: bookLanguage)
    DataManager.UserDefaultsManager.set(readPageDict, for: .lastReadPage)
}

For me, I'm seeing an "Index from 0" vs. "Index from 1" issue. I believe that under the hood some changes have recently been made to PDFKit.

It's possible this wouldn't have worked in the past...

Using Apple Swift version 5.2.4 (swiftlang-1103.0.32.9 clang-1103.0.32.53) Target: x86_64-apple-darwin19.5.0 and Xcode Version 11.5 (11E608c)

This works for me:

   var currentPageNumber: Int  {
        let result = pdfView.currentPage?.pageRef?.pageNumber ?? 0
        return result > 0 ? result - 1 : 0
    }

One Possible way to save the currently viewed page's page number:

    /// integer(forKey:) returns 0 when not found, which is perfect place to scroll to
    /// this only addresses the case you are viewing the same document that was saved to user defaults
    /// if you've gone to a new file, start at 0 there
    /// you could update the document proxy to contain a last page saved if you have one, 
    /// and when opening the pdf, save that to user defaults
    func saveCurrentPageNumber() {
        UserDefaults.standard.set(currentPageNumber, forKey: pageNumberKey)
    }

I call this from viewWillAppear()

/// Check user defaults and scroll to last page viewed (or 0 if none)
func scrollToSavedPage() {
    let pageNumber = UserDefaults.standard.integer(forKey: pageNumberKey)
    if let goToPage = document?.page(at: pageNumber) {
        pdfView.go(to: goToPage)
    }
}

Again: YMMV , but this works for me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM