簡體   English   中英

PDFKit 不能在 iPad 上運行,而在模擬器上運行良好 [iOS, Swift]

[英]PDFKit doesn’t work on iPads while works fine on a simulator [iOS, Swift]

我正在學習如何在 iOS 中構建基於document-based應用程序。

我按照 Apple 的官方示例( https://developer.apple.com/documentation/uikit/view_controllers/building_a_document_browser-based_app#overview )並嘗試修改它以顯示 PDF 查看器。

我修改了原始示例代碼以創建以下代碼。 它在我的 Macbook Pro(2020)上的任何模擬器上都可以正常工作。 但是,當我使用 iPad(即 iPad Mini 和 iPad Pro:新一代)進行測試時,我無法打開 PDF 文件。

我發現以下代碼不起作用: let doc = PDFDocument(url: documentURL) 該 URL 似乎是適當獲取的。 使用 iPad 進行測試時, doc仍然nil ,而在使用模擬器進行測試時適當地獲得。

如果您能讓我知道我的代碼有什么問題,我將不勝感激。

DocumentBrowserController.swift

import UIKit
import os.log
import PDFKit

/// - Tag: DocumentBrowserViewController
class DocumentBrowserViewController: UIDocumentBrowserViewController, UIDocumentBrowserViewControllerDelegate {
    
    /// - Tag: viewDidLoad
    override func viewDidLoad() {
        super.viewDidLoad()
        delegate = self
        
        allowsDocumentCreation = true
        allowsPickingMultipleItems = false
    }
    
     //MARK: - UIDocumentBrowserViewControllerDelegate
    
    // UIDocumentBrowserViewController is telling us to open a selected a document.
    func documentBrowser(_ controller: UIDocumentBrowserViewController, didPickDocumentsAt documentURLs: [URL]) {
        if let url = documentURLs.first {
            presentDocument(at: url)
        }
    }
    
    // MARK: - Document Presentation
   var transitionController: UIDocumentBrowserTransitionController?
    
    func presentDocument(at documentURL: URL) {
        let storyBoard = UIStoryboard(name: "Main", bundle: nil)

        // Load the document's view controller from the storyboard.
        let instantiatedNavController = storyBoard.instantiateViewController(withIdentifier: "DocNavController")
        guard let docNavController = instantiatedNavController as? UINavigationController else { fatalError() }
        guard let documentViewController = docNavController.topViewController as? TextDocumentViewController else { fatalError() }
        
//        // Load the document view.
//        documentViewController.loadViewIfNeeded()
//
        // In order to get a proper animation when opening and closing documents, the DocumentViewController needs a custom view controller
        // transition. The `UIDocumentBrowserViewController` provides a `transitionController`, which takes care of the zoom animation. Therefore, the
        // `UIDocumentBrowserViewController` is registered as the `transitioningDelegate` of the `DocumentViewController`. Next, obtain the
        // transitionController, and store it for later (see `animationController(forPresented:presenting:source:)` and
        // `animationController(forDismissed:)`).
        docNavController.transitioningDelegate = self
        
        // Get the transition controller.
        transitionController = transitionController(forDocumentAt: documentURL)
        
        let doc = PDFDocument(url: documentURL)

        transitionController!.targetView = documentViewController.pdfView
  
        
        // Present this document (and it's navigation controller) as full screen.
        docNavController.modalPresentationStyle = .fullScreen

        // Set and open the document.
        documentViewController.document = doc
        os_log("==> Document Opened", log: .default, type: .debug)
        self.present(docNavController, animated: true, completion: nil)
    }
    
}

extension DocumentBrowserViewController: UIViewControllerTransitioningDelegate {
    
    func animationController(forPresented presented: UIViewController,
                             presenting: UIViewController,
                             source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        // Since the `UIDocumentBrowserViewController` has been set up to be the transitioning delegate of `DocumentViewController` instances (see
        // implementation of `presentDocument(at:)`), it is being asked for a transition controller.
        // Therefore, return the transition controller, that previously was obtained from the `UIDocumentBrowserViewController` when a
        // `DocumentViewController` instance was presented.
        return transitionController
    }
    
    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        // The same zoom transition is needed when closing documents and returning to the `UIDocumentBrowserViewController`, which is why the the
        // existing transition controller is returned here as well.
        return transitionController
    }
    
}

TextDocumentViewController.swift

(我也只是在這里發布這個,雖然這段代碼似乎不是問題)

/*
 See LICENSE folder for this sample’s licensing information.
 
 Abstract:
 A view controller for displaying and editing documents.
 */

import UIKit
import os.log
import PDFKit

var currentPage = 0

/// - Tag: textDocumentViewController
class TextDocumentViewController: UIViewController, PDFDocumentDelegate, PDFViewDelegate {
    
    @IBOutlet weak var pdfView: PDFView!
    @IBOutlet weak var doneButton: UIBarButtonItem!
    
    private var keyboardAppearObserver: Any?
    private var keyboardDisappearObserver: Any?
    
    var document: PDFDocument! {
        didSet {
            document.delegate = self
        }
    }
    
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        //        setupNotifications()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        //        setupNotifications()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        pdfView.delegate = self
        doneButton.isEnabled = false
        
        if #available(iOS 13.0, *) {
            /** When turned on, this changes the rendering scale of the text to match the standard text scaling
             and preserves the original font point sizes when the contents of the text view are copied to the pasteboard.
             Apps that show a lot of text content, such as a text viewer or editor, should turn this on and use the standard text scaling.
             
             For more information, refer to the WWDC 2019 video on session 227 "Font Management and Text Scaling"
             https://developer.apple.com/videos/play/wwdc2019/227/
             (from around 30 minutes in, and to the end)
             */
        }
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        pdfView.document = document!
        pdfView.autoScales = true
        pdfView.displayMode  = .singlePage
        pdfView.displayDirection = .horizontal
        pdfView.displaysPageBreaks = true
        pdfView.pageBreakMargins = UIEdgeInsets(top: 10, left: 20, bottom: 10, right: 20)
        pdfView.usePageViewController(true)                   
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        
    }
    
    
    
}

* 我簡化了代碼,試圖清楚地說明問題 (2020/10/27)

您好,我認為這可能是因為:

documentBrowser(_ controller: UIDocumentBrowserViewController, didPickDocumentsAt documentURLs: [URL]) 

訪問沙箱外的項目。

你可以嘗試更換:

 presentDocument(at: url)

let data = try? Data(contentsOf: url)
print(data)

如果這打印 nil,那是因為 URL 加載失敗。

然后將其替換為:

   let didObtainSecScope = url.startAccessingSecurityScopedResource()
   let data = try? Data(contentsOf: url)
   print(data, didObtainSecScope)
   url.stopAccessingSecurityScopedResource()

如果我的懷疑是正確的,它應該打印一個描述數據對象,然后是“true”。 您應該能夠用您的 PDF 代碼替換“Data(contentsOf: url)”。 您必須在使用 URL 時維護安全范圍,然后在使用完 URL 處的文檔后調用“url.stopAccessingSecurityScopedResource”。 否則你會泄漏內核資源。

確保不要過早調用“stopAccessingSecurityScopedResource()”。

編輯:這里的蘋果文檔中明確提到了這一點: https : //developer.apple.com/documentation/uikit/view_controllers/providing_access_to_directories

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM