Swift实现文档目录PDF预览及UIViewController邮件发送方案咨询
Let’s break this down step by step—first accessing your PDF in the Documents directory, then previewing it in a view controller, and finally integrating email sending with the preview workflow.
1. Accessing the PDF in the Documents Directory
First, you need a reliable way to locate your saved PDF file. Here’s how to retrieve the Documents directory path and target your specific PDF:
func getDocumentsDirectory() -> URL { let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) return paths[0] } // Replace "Order.pdf" with your actual PDF filename func getOrderPDFURL() -> URL? { let docsDir = getDocumentsDirectory() return docsDir.appendingPathComponent("Order.pdf") }
Always add a check to confirm the file exists before proceeding:
if let pdfURL = getOrderPDFURL(), FileManager.default.fileExists(atPath: pdfURL.path) { // PDF exists—proceed to load/preview } else { // Handle missing PDF error }
2. Previewing the PDF in a UIViewController
The modern, native way to preview PDFs on iOS is using PDFKit (available from iOS 11 onwards). Here’s a complete view controller implementation:
Step 1: Import Required Frameworks
Add these imports at the top of your file:
import UIKit import PDFKit
Step 2: Build the Preview View Controller
class PDFPreviewViewController: UIViewController { private var pdfView: PDFView! override func viewDidLoad() { super.viewDidLoad() setupPDFView() loadPDF() addSendEmailButton() // Add this to trigger email later } private func setupPDFView() { pdfView = PDFView() pdfView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(pdfView) // Make the PDF view fill the entire screen NSLayoutConstraint.activate([ pdfView.topAnchor.constraint(equalTo: view.topAnchor), pdfView.leadingAnchor.constraint(equalTo: view.leadingAnchor), pdfView.trailingAnchor.constraint(equalTo: view.trailingAnchor), pdfView.bottomAnchor.constraint(equalTo: view.bottomAnchor) ]) // Configure user-friendly settings pdfView.displayMode = .singlePageContinuous pdfView.autoScales = true pdfView.backgroundColor = .white } private func loadPDF() { guard let pdfURL = getOrderPDFURL(), FileManager.default.fileExists(atPath: pdfURL.path) else { showErrorAlert(message: "Order PDF not found in documents directory") return } if let pdfDocument = PDFDocument(url: pdfURL) { pdfView.document = pdfDocument } else { showErrorAlert(message: "Failed to load the PDF file") } } // Helper to show error alerts private func showErrorAlert(message: String) { let alert = UIAlertController(title: "Oops", message: message, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default)) present(alert, animated: true) } // Reuse the directory helper functions from section 1 func getDocumentsDirectory() -> URL { let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) return paths[0] } func getOrderPDFURL() -> URL? { let docsDir = getDocumentsDirectory() return docsDir.appendingPathComponent("Order.pdf") } }
3. Adding Email Sending Functionality
To send the PDF via email, use MFMailComposeViewController. Integrate this into your preview view controller:
Step 1: Import MessageUI
Add this import to your file:
import MessageUI
Step 2: Add Send Button & Email Composer
Add these functions to your PDFPreviewViewController:
private func addSendEmailButton() { let sendButton = UIBarButtonItem(title: "Send Order", style: .done, target: self, action: #selector(sendEmailTapped)) navigationItem.rightBarButtonItem = sendButton } @objc private func sendEmailTapped() { guard MFMailComposeViewController.canSendMail() else { showErrorAlert(message: "Email is not configured on this device") return } guard let pdfURL = getOrderPDFURL(), let pdfData = try? Data(contentsOf: pdfURL) else { showErrorAlert(message: "Could not attach the order PDF") return } let mailComposer = MFMailComposeViewController() mailComposer.mailComposeDelegate = self // Customize your email content mailComposer.setSubject("Your Order Confirmation") mailComposer.setMessageBody("Please find your order details attached below.", isHTML: false) // Attach the PDF file mailComposer.addAttachmentData(pdfData, mimeType: "application/pdf", fileName: "Order.pdf") present(mailComposer, animated: true) }
Step 3: Handle Email Composer Dismissal
Add this extension to conform to the mail delegate:
extension PDFPreviewViewController: MFMailComposeViewControllerDelegate { func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) { controller.dismiss(animated: true) // Give user feedback based on result switch result { case .sent: let successAlert = UIAlertController(title: "Success", message: "Order email sent!", preferredStyle: .alert) successAlert.addAction(UIAlertAction(title: "OK", style: .default)) present(successAlert, animated: true) case .failed: showErrorAlert(message: "Failed to send email: \(error?.localizedDescription ?? "Unknown error")") case .saved: let savedAlert = UIAlertController(title: "Saved", message: "Email saved to drafts", preferredStyle: .alert) savedAlert.addAction(UIAlertAction(title: "OK", style: .default)) present(savedAlert, animated: true) default: break // No action needed for cancelled emails } } }
Key Tips
- PDFKit vs WKWebView: PDFKit is purpose-built for PDFs (supports zoom, page navigation, and annotations), making it the better choice for native PDF previews. WKWebView works too but lacks PDF-specific features.
- Error Handling: Always validate file existence and email configuration to avoid crashes and improve user experience.
- Testing: When testing email functionality, use a real device (simulators don’t support email sending).
内容的提问来源于stack exchange,提问作者Bob Mehr

