iOS开发:使用PDFKit从相机拍摄图片生成PDF及相关问题咨询
Hey there! As someone who’s worked with PDFKit and iOS image handling a fair bit, let’s walk through your questions step by step to get you sorted.
When you take a photo via UIImagePickerController, the system generates a default filename for the image, but it’s not directly available in the info dictionary. Instead, we can use the Photos framework to fetch this name through a PHAsset:
- First, make sure you’ve added the
Photosframework to your project, and addedNSPhotoLibraryUsageDescriptionto yourInfo.plist(you need this permission to access album assets). - In your
imagePickerController(_:didFinishPickingMediaWithInfo:)method, retrieve thePHAssetfrom the info dict and fetch the filename:
import Photos func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { picker.dismiss(animated: true) // Fetch the PHAsset associated with the photo if let asset = info[.phAsset] as? PHAsset { PHImageManager.default().requestImageDataAndOrientation(for: asset, options: nil) { data, _, _, infoDict in // Extract the file name from the returned info dictionary if let fileURL = infoDict?["PHImageFileURLKey"] as? URL { let imageName = fileURL.lastPathComponent print("Image filename: \(imageName)") // Use this name for your PDF conversion logic } } } // Your existing code to save the image to the album... }
If you don’t need the system-generated filename, you can also create a custom one (like using a timestamp) for simplicity:
let customImageName = "captured_photo_\(Date().timeIntervalSince1970).jpg"
Absolutely! PDFKit has all the tools you need to create a PDF where users can move, scale, or delete images. Here’s a high-level approach:
Step 1: Create a PDF with your image
First, convert your UIImage into a PDFPage and add it to a PDFDocument:
import PDFKit func createPDFWithImage(_ image: UIImage) -> PDFDocument { let pdfDoc = PDFDocument() guard let pdfPage = PDFPage(image: image) else { return pdfDoc } pdfDoc.insert(pdfPage, at: 0) return pdfDoc }
Step 2: Add images as editable annotations
To make images interactive, wrap them in PDFAnnotation (this makes it easier to handle gestures for editing):
func addEditableImage(to pdfPage: PDFPage, image: UIImage, at position: CGPoint) { let imageBounds = CGRect(origin: position, size: image.size) let imageAnnotation = PDFAnnotation(bounds: imageBounds, forType: .stamp, withProperties: nil) imageAnnotation.image = image imageAnnotation.shouldDisplay = true pdfPage.addAnnotation(imageAnnotation) }
Step 3: Add gesture recognizers for editing
Add pan, pinch, and long-press gestures to your PDFView to handle moving, scaling, and deleting annotations:
// Add gestures to your PDFView in viewDidLoad() override func viewDidLoad() { super.viewDidLoad() let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:))) let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch(_:))) let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(_:))) pdfView.addGestureRecognizer(panGesture) pdfView.addGestureRecognizer(pinchGesture) pdfView.addGestureRecognizer(longPressGesture) } // Handle pan to move the selected annotation @objc func handlePan(_ gesture: UIPanGestureRecognizer) { guard let pdfView = gesture.view as? PDFView, let selectedAnnotation = pdfView.currentSelection?.annotations.first as? PDFAnnotation, gesture.state == .changed else { return } let translation = gesture.translation(in: pdfView) selectedAnnotation.bounds = selectedAnnotation.bounds.offsetBy(dx: translation.x, dy: translation.y) gesture.setTranslation(.zero, in: pdfView) } // Handle pinch to scale the selected annotation @objc func handlePinch(_ gesture: UIPinchGestureRecognizer) { guard let pdfView = gesture.view as? PDFView, let selectedAnnotation = pdfView.currentSelection?.annotations.first as? PDFAnnotation, gesture.state == .changed else { return } let scale = gesture.scale selectedAnnotation.bounds = selectedAnnotation.bounds.applying(CGAffineTransform(scaleX: scale, y: scale)) gesture.scale = 1.0 } // Handle long press to delete the annotation @objc func handleLongPress(_ gesture: UILongPressGestureRecognizer) { guard let pdfView = gesture.view as? PDFView, let selectedAnnotation = pdfView.currentSelection?.annotations.first, gesture.state == .began else { return } let alert = UIAlertController(title: "Delete Image?", message: "Remove this image from the PDF?", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "Delete", style: .destructive) { _ in selectedAnnotation.page?.removeAnnotation(selectedAnnotation) }) alert.addAction(UIAlertAction(title: "Cancel", style: .cancel)) present(alert, animated: true) }
Step 4: Save the edited PDF
Once the user is done editing, save the PDF to the document directory:
func saveEditedPDF(_ document: PDFDocument) { let docsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] let saveURL = docsDir.appendingPathComponent("edited_pdf.pdf") document.write(to: saveURL) // You can then share this URL or save it to the user's files }
UIImagePickerController Code (Polished) Here’s a clean version of the image picker code you referenced:
import UIKit import Photos class PhotoCaptureViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate { override func viewDidLoad() { super.viewDidLoad() // Set up your UI (e.g., a "Take Photo" button) here } @IBAction func takePhotoButtonTapped(_ sender: UIButton) { guard UIImagePickerController.isSourceTypeAvailable(.camera) else { print("Camera not available on this device") return } let imagePicker = UIImagePickerController() imagePicker.sourceType = .camera imagePicker.delegate = self imagePicker.allowsEditing = false // Set to true if you want post-capture editing present(imagePicker, animated: true) } func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { picker.dismiss(animated: true) guard let capturedImage = info[.originalImage] as? UIImage else { print("Failed to retrieve captured image") return } // Save image to photo album UIImageWriteToSavedPhotosAlbum(capturedImage, self, #selector(imageSaveCompletion(_:didFinishSavingWithError:contextInfo:)), nil) // Here you can call your PDF creation/editing methods let pdfDoc = createPDFWithImage(capturedImage) pdfView.document = pdfDoc } @objc func imageSaveCompletion(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) { if let error = error { print("Error saving image: \(error.localizedDescription)") } else { print("Image saved to photo album successfully") } } func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { picker.dismiss(animated: true) } }
内容的提问来源于stack exchange,提问作者neda Derakhshesh

