Swift 3.0:使用 URLSessionDownloadDelegate 完成下载后如何在不同的视图控制器中打开 PDF

Posted

技术标签:

【中文标题】Swift 3.0:使用 URLSessionDownloadDelegate 完成下载后如何在不同的视图控制器中打开 PDF【英文标题】:Swift 3.0: How to open a PDF in a different view controller when finished downloading using URLSessionDownloadDelegate 【发布时间】:2016-12-14 19:30:41 【问题描述】:

在我正在编写的应用程序中,我需要从服务器下载 PDF 并将其显示在 UIWebView 中。为此,我有一些代码可以从端点检索 PDF(它不是 URL,在台式计算机上,打开一个对话框以在浏览器中保存)并通过抓取将其加载到设备上名为 PDFGrabber 的类中的数据:

func getPDF(completionHandler:@escaping (URL) -> Void)

    let theURL:String = "https://mywebsite.com/Endpoint"
    let fileURL:URL = URL(string: theURL)!
    var request = URLRequest(url: fileURL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
    let session = URLSession.shared

    let task = session.dataTask(with: request, completionHandler: data, response, error -> Void in

    var documentURL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)).last
    documentURL = documentURL?.appendingPathComponent("MyDocument.pdf")

    do
    
        try data?.write(to: documentURL!, options: .atomic)
        completionHandler(documentURL!)
        
        catch
        
            print(error)
        
    )

    task.resume()

然后,在显示 PDF 的表格视图控制器中(我们称之为 PDFTableView,当请求 PDF 时(通过点击表格中的单元格),我可以使用 PDFGrabber 中的 documentURL:

PDFGrabber.getPDF()fileURL -> () in
    DispatchQueue.main.async
    
        if let resultController = self.storyboard!.instantiateViewController(withIdentifier: "PDFViewer") as? PDFViewer 
        
            resultController.thePDFPath = stringURL
            self.present(resultController, animated: true, completion: nil)
        
    

最后,我在 PDFViewer 视图控制器中有另一个带有 UIWebView 的视图控制器,名为“WebView”,属性“thePDFPath”作为字符串。在 viewDidLoad() 方法中,我可以说:

override func viewDidLoad()

    let pathToPDF:URL = URL(string: thePDFPath)!
    WebView.loadRequest(URLRequest(url: pathToPDF))

这会将 PDF 加载到 Web 视图中。但是,加载时间可能有点慢,我希望能够使用进度条和字符串计算有多少 PDF 已加载到用户的设备上。从其他问题中,我收集到我需要让我的 PDFGrabber 类扩展 URLSessionDownloadDelegate,然后实现这些功能。获取下载的字节数很简单,因为我可以简单地去:

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten writ: Int64, totalBytesExpectedToWrite exp: Int64)

    percentDownloaded = (Float(writ)/Float(exp)) * 100
    print("Progress: " + String(describing: percentDownloaded))

但我也希望仅在 PDF 以百分比显示进度后完全下载后才能打开 PDFView(我有一个覆盖视图)。之前,我可以使用完成处理程序并等待 PDF 完成下载,然后再打开它。

但是,这种方法不允许我访问下载的字节数;我可以从

中打开视图吗
urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)

功能,或者我还有什么需要做的吗?

非常感谢您的建议;谢谢!

【问题讨论】:

【参考方案1】:

导入 WebKit

您可以在此处将 pdf 加载到您的应用程序中

 override func viewDidLoad() 
      super.viewDidLoad()
      // Do any additional setup after loading the view, typically from a nib.

      if let pdfURL = Bundle.main.url(forResource: "food-and-drink-menu-trafalgar-tavern", withExtension: "pdf", subdirectory: nil, localization: nil)  
           do 
                let data = try Data(contentsOf: pdfURL)
                let webView = WKWebView(frame: CGRect(x:0,y:NavigationView.frame.size.height,width:view.frame.size.width, height:view.frame.size.height-NavigationView.frame.size.height))
                webView.load(data, mimeType: "application/pdf", characterEncodingName:"", baseURL: pdfURL.deletingLastPathComponent())
                view.addSubview(webView)

           
           catch 
                // catch errors here
           

      
 

【讨论】:

以上是关于Swift 3.0:使用 URLSessionDownloadDelegate 完成下载后如何在不同的视图控制器中打开 PDF的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift 3.0 中使用 keysSortedByValue?

使用 FBSDKProfileExpressionKit 上传 Facebook 个人资料图片 - swift 3.0

Swift 3.0 Date的简单使用

从 Swift 3.0 转换为 Swift 2.3

swift 3.0 值得现在去使用吗

Swift 3.0 闭包的定义和使用