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
If Let Doesn't Unwrap Optional Value for Mkannotation's Title Property
How to Update a Sent Message in Quickblox iOS
Swift/How to Call Delegate with Popviewcontroller
Square Video Using Avfoundation
iPhone Simulator Plays Video, Real Device Won'T
Exception: Cannot Manually Set the Delegate on a Uinavigationbar Managed by a Controller
Video Thumbnail Taking 10-15 Secs to Display
Displaying Instances of View Controllers Within Xcode Without Disturbing the Current Hierarchy
Change Selected Row Label Color in Picker View Swift 1.2
Empty Return Value from Swift Function Containing Closure
Fbsdk (New Facebook Sdk 4.0) Implementation Is Not Working for Login with Facebook
Ios-Charts How to Put Uiimage Beside a Point
Checking If Text Fields Are Empty Cause Error in Swift 2