When I try to use PDFDocument.init(url: )
, I noticed that it worked with http
but not with https
URLs. Does anyone know why?
import PDFKit
let httpURL = URL(string: "http://www.axmag.com/download/pdfurl-guide.pdf")!
let doc1 = PDFDocument(url: httpURL) //makes a PDFDocument
let httpsURL = URL(string: "https://www.gnu.org/s/libmicrohttpd/tutorial.pdf")!
let doc2 = PDFDocument(url: httpsURL) //nil
@IBOutlet var pdfView: PDFView!
var pdfDOC: PDFDocument!
override func viewDidLoad() {
super.viewDidLoad()
downloadPDF()
}
func downloadPDF(){
let urlString = "https://www.tutorialspoint.com/swift/swift_tutorial.pdf"
guard let url = URL(string: urlString) else {return}
do{
let data = try Data(contentsOf: url)
pdfDOC = PDFDocument(data: data)
pdfView.displayMode = .singlePageContinuous
pdfView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
pdfView.displaysAsBook = true
pdfView.displayDirection = .vertical
pdfView.document = pdfDOC
pdfView.autoScales = true
pdfView.maxScaleFactor = 4.0
pdfView.minScaleFactor = pdfView.scaleFactorForSizeToFit
}catch let err{
print(err.localizedDescription)
}
}
At first glance, this appears to be kind of a common problem in the Cocoa frameworks; many APIs take URLs, but in many cases, it's not clear what schemes they will accept. Some only take file URLs, some only take HTTP, some take HTTP, and HTTPS, and the documentation often doesn't say anything about which is going to be the case. It's often a good assumption that if the documentation doesn't say otherwise, the API probably only accepts file:
URLs.
However, when you look a little deeper, it's not as much of a problem as it appears at first glance. In your case, you can work around the problem trivially by using Data's try init(contentsOf:)
, which does support HTTPS, and then initializing your PDFDocument
from that, but this isn't actually the best way to go about it. What I'd actually recommend doing instead would be to use an asynchronous API like URLSession
to load the PDF data from the server. The reason I suggest this is that loading data from the network can take time, especially with PDF files which can sometimes be quite large, and if you just try to load the file synchronously on the main thread, you'll block it and make your app appear as if it is locked up. By loading the PDF data asynchronously, you can provide progress information for your user, along with a way to cancel the operation, and if something goes wrong, like the network going down in the middle of the download, you can handle that error in a sensible way. Once the data's all downloaded, you can then use the resulting Data object to initialize a PDFDocument
.
So to answer your question, my guess as to why PDFDocument
doesn't support HTTPS is because a synchronous initializer like this isn't the recommended way to load something over a network, and thus, putting a lot of work into designing it for that purpose was not a priority.
Here is a link to Apple's recommendation that your networking be asynchronous: https://developer.apple.com/library/content/documentation/NetworkingInternetWeb/Conceptual/NetworkingOverview/Introduction/Introduction.html#//apple_ref/doc/uid/TP40010220-CH12-SW3
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With