How to Open a Local PDF File Using a Swiftui Button

In my Mac app, how can I open a local PDF file using a SwiftUI button?

macOS 11, iOS 14

There is a native SwiftUI view modifier for the QuickLook preview since macOS 11 / iOS 14. You can set the binding to the URL to your PDF File (or any other type that can be shown in QuickLook). Then the system presents the file. If the binding value is nil, the preview will not show or will be dismissed if currently shown.

.quickLookPreview(_ item: Binding<URL?>)

How can I open a local PDF file using a SwiftUI button?

Using PDFKit we load local PDF file. Please try below code.

import SwiftUI
struct ResumeView: View {
....
let fileUrl = Bundle.main.url(forResource: "Resume", withExtension: "pdf")!
var body: some View {
....
Button(action: {
PDFKitView(url: self.fileUrl)
}) {
Text(text)
.foregroundColor(.black)
}
....
}
}

PDFKitView

import PDFKit
struct PDFKitView: View {
var url: URL
var body: some View {
PDFKitRepresentedView(url)
}
}

struct PDFKitRepresentedView: UIViewRepresentable {
let url: URL
init(_ url: URL) {
self.url = url
}

func makeUIView(context: UIViewRepresentableContext<PDFKitRepresentedView>) -> PDFKitRepresentedView.UIViewType {
let pdfView = PDFView()
pdfView.document = PDFDocument(url: self.url)
pdfView.autoScales = true
return pdfView
}

func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<PDFKitRepresentedView>) {
// Update the view.
}
}

Open PDF file using swift

If you simply want to view a PDF file you can load it into a UIWebView.

let url : NSURL! = NSURL(string: "http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIWebView_Class/UIWebView_Class.pdf")
webView.loadRequest(NSURLRequest(URL: url))

Swift 4.1 :

let url: URL! = URL(string: "http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIWebView_Class/UIWebView_Class.pdf")
webView.loadRequest(URLRequest(url: url))

If you'd like to achieve more, a good framework is PSPDFKit.

How to implement PDF Viewer to SwiftUI application?

To display a PDF with Apple-only frameworks, you'll need to use UIKit, via a UIViewRepresentable:

import PDFKit
import SwiftUI

struct PDFKitRepresentedView: UIViewRepresentable {
typealias UIViewType = PDFView

let data: Data
let singlePage: Bool

init(_ data: Data, singlePage: Bool = false) {
self.data = data
self.singlePage = singlePage
}

func makeUIView(context _: UIViewRepresentableContext<PDFKitRepresentedView>) -> UIViewType {
// Create a `PDFView` and set its `PDFDocument`.
let pdfView = PDFView()
pdfView.document = PDFDocument(data: data)
pdfView.autoScales = true
if singlePage {
pdfView.displayMode = .singlePage
}
return pdfView
}

func updateUIView(_ pdfView: UIViewType, context _: UIViewRepresentableContext<PDFKitRepresentedView>) {
pdfView.document = PDFDocument(data: data)
}
}

then PDFKitRepresentedView can be used in your view hierarchy.

This takes a Data object as input, so you'll need to convert those URL objects you have to Data via a network call first. So, you might do something like:

@State var data : Data? 

...

.onAppear {
self.data = try? Data(contentsOf: url)
}

Keep in mind this is vastly simplified -- you'll want to do some error handling, etc. Might want to do some searching on SwiftUI network calls.

How to Load Local PDF in UIWebView in Swift

Here you go:

if let pdf = NSBundle.mainBundle().URLForResource("myPDF", withExtension: "pdf", subdirectory: nil, localization: nil)  {
let req = NSURLRequest(URL: pdf)
let webView = UIWebView(frame: CGRectMake(20,20,self.view.frame.size.width-40,self.view.frame.size.height-40))
webView.loadRequest(req)
self.view.addSubview(webView)
}

Edit

The alternative is via NSData:

if let pdfURL = NSBundle.mainBundle().URLForResource("myPDF", withExtension: "pdf", subdirectory: nil, localization: nil),data = NSData(contentsOfURL: pdfURL), baseURL = pdfURL.URLByDeletingLastPathComponent  {
let webView = UIWebView(frame: CGRectMake(20,20,self.view.frame.size.width-40,self.view.frame.size.height-40))
webView.loadData(data, MIMEType: "application/pdf", textEncodingName:"", baseURL: baseURL)
self.view.addSubview(webView)
}

Apple make a point of advising you to not use .loadRequest for local HTML files, while not clearly extending this to other data types. So I've provided the NSData route above. If you wish to specify a textEncodingName it can be "utf-8", "utf-16", etc.

Edit: Swift 3

Here's a Swift 3 version of the code using, as Apple advise, WKWebView in place of UIWebView.

import UIKit
import WebKit

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

if let pdfURL = Bundle.main.url(forResource: "myPDF", withExtension: "pdf", subdirectory: nil, localization: nil) {
do {
let data = try Data(contentsOf: pdfURL)
let webView = WKWebView(frame: CGRect(x:20,y:20,width:view.frame.size.width-40, height:view.frame.size.height-40))
webView.load(data, mimeType: "application/pdf", characterEncodingName:"", baseURL: pdfURL.deletingLastPathComponent())
view.addSubview(webView)

}
catch {
// catch errors here
}

}
}

}

Accessing the PDF from Asset.xcassets (Swift 4)

if let asset = NSDataAsset(name: "myPDF") {
let url = Bundle.main.bundleURL
let webView = WKWebView(frame: CGRect(x:20,y:20,width:view.frame.size.width-40, height:view.frame.size.height-40))
webView.load(asset.data, mimeType: "application/pdf", characterEncodingName:"", baseURL:url)
view.addSubview(webView)
}

How to open the Document files e.g(.pdf,.doc,.docx) in ios mobile when a button action using swift3.0?

Swift 3*, 4*,

To open document and select any document, you are using UIDocumentPickerViewController then all documents presented in your iCloud, Files and in Google Drive will be shown if Google Drive is connected in user device. Then selected document need to download in your app and from there you can show it in WKWebView,

   @IBAction func uploadNewResumeAction(_ sender: Any) {

/* let documentPicker = UIDocumentPickerViewController(documentTypes: ["com.apple.iwork.pages.pages", "com.apple.iwork.numbers.numbers", "com.apple.iwork.keynote.key","public.image", "com.apple.application", "public.item","public.data", "public.content", "public.audiovisual-content", "public.movie", "public.audiovisual-content", "public.video", "public.audio", "public.text", "public.data", "public.zip-archive", "com.pkware.zip-archive", "public.composite-content", "public.text"], in: .import) */

let documentPicker = UIDocumentPickerViewController(documentTypes: ["public.text", "com.apple.iwork.pages.pages", "public.data"], in: .import)

documentPicker.delegate = self
present(documentPicker, animated: true, completion: nil)
}

extension YourViewController: UIDocumentPickerDelegate{

func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {

let cico = url as URL
print(cico)
print(url)

print(url.lastPathComponent)

print(url.pathExtension)

}
}

Note: If you intend to select all files the you have to use following code:

  let documentPicker = UIDocumentPickerViewController(documentTypes: ["com.apple.iwork.pages.pages", "com.apple.iwork.numbers.numbers", "com.apple.iwork.keynote.key","public.image", "com.apple.application", "public.item","public.data", "public.content", "public.audiovisual-content", "public.movie", "public.audiovisual-content", "public.video", "public.audio", "public.text", "public.data", "public.zip-archive", "com.pkware.zip-archive", "public.composite-content", "public.text"], in: .import) 

In your action method.

How to open pdf file in swift directly from URL

You are trying to load a http-Url into a WebView which is prohibited by default in iOS. You can try the same code with an https-Url or change your Transport Security Settings in the Info.plist to allow Arbitrary loads

Another useful idea might be to use SFSafariViewController to show a website or document from another url.

Is it possible to display PDF thumbnails in SwiftUI app?

To display a PDF thumbnail in SwiftUI, you'll need to wrap PDFThumbnailView, which is a UIView in UIViewRepresentable.

Something like:

import PDFKit
import SwiftUI

struct PDFThumbnailRepresented : UIViewRepresentable {
var pdfView : PDFView

func makeUIView(context: Context) -> PDFThumbnailView {
let thumbnail = PDFThumbnailView()
thumbnail.pdfView = pdfView
thumbnail.thumbnailSize = CGSize(width: 100, height: 100)
thumbnail.layoutMode = .horizontal
return thumbnail
}

func updateUIView(_ uiView: PDFThumbnailView, context: Context) {
//do any updates you need
//you could update the thumbnailSize to the size of the view here if you want, for example
//uiView.thumbnailSize = uiView.bounds.size
}
}

You'd use it by passing a PDFView: PDFThumbnailRepresented(pdfView: pdfView)

To create your PDFView, you'll need to get the data or url and create it something like:

guard let path = Bundle.main.url(forResource: "example", withExtension: "pdf") else { return }

if let document = PDFDocument(url: path) {
pdfView.document = document
}

Note the above sample is if it was in your app's Bundle. Your question about loading it from Firebase Storage is beyond the scope of just this question which I'm assuming to be about just displaying the PDF thumbnail in SwiftUI.

More resources about loading/creating the PDFThumbnailView, not including wrapping it like I did above: https://www.hackingwithswift.com/example-code/libraries/how-to-show-pdf-thumbnails-using-pdfthumbnailview



Related Topics



Leave a reply



Submit