Display and manipulate PDF documents in your applications using PDFKit.

Posts under PDFKit tag

69 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

Files App Share Context with Security scoped resource fails
I'm creating an App that can accepted PDFs from a shared context. I am using iOS, Swift, and UIKit with IOS 17.1+ The logic is: get the context see who is sending in (this is always unknown) see if I can open in place (in case I want to save later) send the URL off to open the (PDF) document and load it into PDFKit's pdfView.document I have no trouble loading PDF docs with the file picker. And everything works as expected for shares from apps like Messages, email, etc... (in which case URLContexts.first.options.openInPlace == False) The problem is with opening (sharing) a PDF that is sent from the Files App. (openInPlace == True) If the PDF is in the App's Document Folder, I need the Security scoped resource, to access the URL from the File's App so that I can copy the PDF's data to the PDFViewer.document. I get Security scoped resource access granted each time I get the File App's context URL. But, when I call fileCoordinator.coordinate and try to access a file outside of the App's document folder using the newUrl, I get an error. FYI - The newUrl (byAccessor) and context url (readingItemAt) paths are always same for the Files App URL share context. I can, however, copy the file to a new location in my apps directory and then open it from there and load in the data. But I really do not want to do that. . . . . . Questions: Am I missing something in my pList or are there other parameters specific to sharing a file from the Files App? I'd appreciate if someone shed some light on this? . . . . . Here are the parts of my code related to this with some print statements... . . . . . SceneDelegate func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { // nothing to see here, move along guard let urlContext = URLContexts.first else { print("No URLContext found") return } // let's get the URL (it will be a PDF) let url = urlContext.url let openInPlace = urlContext.options.openInPlace let bundleID = urlContext.options.sourceApplication print("Triggered with URL: \(url)") print("Can Open In Place?: \(openInPlace)") print("For Bundle ID: \(bundleID ?? "None")") // get my Root ViewController from window if let rootViewController = self.window?.rootViewController { // currently using just the view if let targetViewController = rootViewController as? ViewController { targetViewController.prepareToLoadSharedPDFDocument(at: url) } // I might use a UINavigationController in the future else if let navigationController = rootViewController as? UINavigationController, let targetViewController = navigationController.viewControllers.first as? ViewController { targetViewController.prepareToLoadSharedPDFDocument(at: url) } } } . . . . ViewController function I broke out the if statement for accessingScope just to make it easier for me the debug and play around with the code in accessingScope == True func loadPDF(fromUrl url: URL) { // If using the File Picker / don't use this // If going through a Share.... we pass the URL and have three outcomes (1, 2a, 2b) // 1. Security scoped resource access NOT needed if from a Share Like Messages or EMail // 2. Security scoped resource access granted/needed from 'Files' App // a. success if in the App's doc directory // b. fail if NOT in the App's doc directory // Set the securty scope variable var accessingScope = false // Log the URLs for debugging print("URL String: \(url.absoluteString)") print("URL Path: \(url.path())") // Check if the URL requires security scoped resource access if url.startAccessingSecurityScopedResource() { accessingScope = true print("Security scoped resource access granted.") } else { print("Security scoped resource access denied or not needed.") } // Stop accessing the scope once everything is compeleted defer { if accessingScope { url.stopAccessingSecurityScopedResource() print("Security scoped resource access stopped.") } } // Make sure the file is still there (it should be in this case) guard FileManager.default.fileExists(atPath: url.path) else { print("File does not exist at URL: \(url)") return } // Let's see if we can open it in place if accessingScope { let fileCoordinator = NSFileCoordinator() var error: NSError? fileCoordinator.coordinate(readingItemAt: url, options: [], error: &error) { (newUrl) in DispatchQueue.main.async { print(url.path()) print(newUrl.path()) if let document = PDFDocument(url: newUrl) { self.pdfView.document = document self.documentFileName = newUrl.deletingPathExtension().lastPathComponent self.fileLoadLocation = newUrl.path() self.updateGUI(pdfLoaded: true) self.setPDFScale(to: self.VM.pdfPageScale, asNewPDF: true) } else { print("Could not load PDF directly from url: \(newUrl)") } } } if let error = error { PRINT("File coordination error: \(error)") } } else { DispatchQueue.main.async { if let document = PDFDocument(url: url) { self.pdfView.document = document self.documentFileName = url.deletingPathExtension().lastPathComponent self.fileLoadLocation = url.path() self.updateGUI(pdfLoaded: true) self.setPDFScale(to: self.VM.pdfPageScale, asNewPDF: true) } else { PRINT("Could not load PDF from url: \(url)") } } } } . . . . Other relevant pList settings I've added are: Supports opening documents in place - YES Document types - PDFs (com.adobe.pdf) UIDocumentBrowserRecentDocumentContentTypes - com.adobe.pdf Application supports iTunes file sharing - YES And iCloud is one for Entitlements with iCloud Container Identifiers Ubiquity Container Identifiers . . . . Thank you in advance!. B
0
0
39
10h
PDFKIT, Static Text, on MacOS
Hi community: I'm trying to create a form PDF form a script in swift on Mac First approach was trying to add a simple and static text not collapsible. But I tried multiple options. And all ends on something that is not a static text. The best approach was to create a textfield not editable with widget PDFKit, but when you go to the preview app on Mac and pass the the mouse over the field, it is highlighted in blue ... Thanks for the support.
0
0
204
Apr ’24
Rotate PDF Annotation
I'm working with PDFKit and trying to rotate PDFAnnotation from a PDFView: Here is my code for a normal case(no rotated): class ImageAnnotation: PDFAnnotation { var image: UIImage? init(image: UIImage?, bounds: CGRect) { self.image = image super.init(bounds: bounds, forType: .stamp, withProperties: nil) } override func draw(with box: PDFDisplayBox, in context: CGContext) { guard let cgImage = self.image?.cgImage else { return } context.draw(cgImage, in: bound) } } And here is the way I used to rotate PDFAnnotation: init(image: UIImage?, bounds: CGRect) { self.image = image super.init(bounds: bounds.applying(CGAffineTransform(rotationAngle: -CGFloat.pi/12)), forType: .stamp, withProperties: nil) } override func draw(with box: PDFDisplayBox, in context: CGContext) { guard let cgImage = self.image?.cgImage else { return } context.rotate(by: CGFloat.pi/12) context.draw(cgImage, in: bounds) } But it doesn't work as expected. Can you help me? Thank you.
0
0
196
Apr ’24
Create an Image from PDFPage in SwiftUI
Im trying to duplicate the display of the built in Files app for documents in my app. How do I convert a page in a PDFDocument to an Image to display as an icon like seen here (from Files App) with SwiftUI. SOLVED: Image(uiImage: (document.page(at: 0)?.thumbnail(of: CGSize(width: 100, height: 100), for: .cropBox))!)
0
0
306
Mar ’24
Blurry and low resolution of PKCanvasView, as overlayview from PDFView.
Hi, I am trying to make a simple note taking app that users can draw something on pdfview with apple pencil. (I used PDFKit, PencilKit for the code.) I followed the instruction code of WWDC22's "What's new in PDFKit." - "overlayProvider" (so you can see the code at the video.) I was able to draw something each view of pdf page. But the issue was, the resolution of overlayview or subview of pdfview is low. As far as I know, the pkcanvasview draws vertor-based drawings. So I never thought the image or the lines I draw will be that blurry. Is this buggy or is this the normal thing? (+ I added a uibutton as subview of pdfview and the button also looks blurry.) I even tried to scale up the all the subviews when the subviews' layout is done, using contentScaleFactor. PKCanvasView inherits UIScrollView, so I enlarged the frame of pkcanvas view and fixed the scale to below 1.0. If the pkcanvasview looks blurry and that is because somewhat zoomed in wrong way, zooming out should be the solution. But, didn't work. Still blurry. and any other stuff like changing frame or size. So, anyone having same problem with me, or anyone can give me any solution. Please help me. I wish this is bug thing that can be fixed in any moment. -> This image is little bit zoomed in. but the drawing is blurry. and this is the normal pkcanvasview drawing, just subview of view(of VC).
1
1
293
Mar ’24
Black image when rendering PDF to image with UIGraphicsImageRendererFormat
Hi everyone, We have been noticing since release iOS 17, that our code which renders PDFPage objects to images was randomly failing (while no error is logged) and produced full black images. This problem seems to mainly occurs on old devices (iPad Pro 2017 and 2018). I mention that this portion code has been running for several years in our app without any issue from iOS10 to iOS16. let renderFormat = UIGraphicsImageRendererFormat.default() renderFormat.opaque = true renderFormat.scale = CGFloat(scale) let renderer = UIGraphicsImageRenderer(size: pageRect.size, format: renderFormat) mainImage = renderer.image { context in // Setup drawing context context.cgContext.setShouldAntialias(false) context.cgContext.setShouldSmoothFonts(false) context.cgContext.setAllowsFontSmoothing(false) context.cgContext.setShouldSubpixelPositionFonts(true) context.cgContext.setShouldSubpixelQuantizeFonts(true) // Draw pdf page context.saveGState() UIColor.white.setFill() context.clip(to: rect) context.fill(rect) page.draw(with: .cropBox, to: context) context.restoreGState() } Did anyone encountered a similar issue? Is there any mean to get an error at least in such cases ? Thanks for any help or advice on this issue.
1
0
247
Mar ’24
PDF Text recognition in WKWebView iOS 16 iOS 17
Problem: Hello! I have some problems with UIEditMenuInteraction in WKWebView which show PDF using PDFKit (as far as I know) - when text is selected, there is no copy/paste buttons on iOS 16.4 or higher. Also I've noticed that selection blue view take less space than actual text is on iOS 17. The problem both cyrillic and latin characters. How I can fix this? p.s. I found on stackoverflow that PDFKit can treat PDF files like images, but on view hierarchy there is no differences between 16 and 17 iOS How it looks: The problem file: https://drive.google.com/file/d/1Tu8RCrlwOI_H3TcwOGFbDR0G9h1OP7MU/view?usp=sharing
0
0
265
Mar ’24
Create a PDF-File of a view with correct papersize
Hello together, does anyone know how I can scale a view to a given document size (e.g. A4: 210/297 mm) without scaling the view itself? With enclosed code I can create the pdf-document, but the paperize is not the intended size. It is too big. Variation this line of code var mediaBox = CGRect(origin: .zero, size: CGSize(width: size.width, height: size.height)) into var mediaBox = CGRect(origin: .zero, size: CGSize(width: 595, height: 842) does not scale the view (it just shows a part of it at the correct papersize). So what do I have to do to scale the rendered view to the proper size? Enclosed a very simple code snipped to see th strange behavior. Thx, best regards Peter import SwiftUI struct ContentView: View { var body: some View { ZStack { Rectangle() .frame(width: 2100, height: 2910) .foregroundColor(.red) Rectangle() .frame(width: 2100/2, height: 2910/3) .foregroundColor(.blue) Text("Hello, world!") } .padding() .onAppear(perform: { generatePDF() }) } // generate pdf from given view @MainActor func generatePDF() -> URL { // Select UI View to render as pdf let image = ImageRenderer(content: ContentView()) let url = URL.documentsDirectory.appending(path: "generatedPDF.pdf") image.render{ size, context in var mediaBox = CGRect(origin: .zero, size: CGSize(width: size.width, height: size.height)) guard let consumer = CGDataConsumer(url: url as CFURL), let pdfContext = CGContext(consumer: consumer, mediaBox: &mediaBox, nil) else { return } pdfContext.beginPDFPage(nil) pdfContext.translateBy(x: mediaBox.size.width / 2 - size.width / 2, y: mediaBox.size.height / 2 - size.height / 2) context(pdfContext) pdfContext.endPDFPage() pdfContext.closePDF() } print("Saving PDF to \(url.path())") return url } } #Preview { ContentView() } ![]("https://developer.apple.com/forums/content/attachment/67b11ec8-af9e-4ab7-a0a5-0c020b7a45d4" "title=generatedPDF (without scaling).jpg;width=2652;height=2526") ![]("https://developer.apple.com/forums/content/attachment/b2c24a25-3805-4664-8adb-dcb81c3e96c4" "title=generatedPDF (with scaling).jpg;width=2132;height=1510")
1
0
339
Mar ’24
Render custom PDFView in PDF with swift
I’m showing a PDF page in UIView’s subview using PDFKit along with some UILabel and UIImageView. At a time I’m only showing one page in PDFView. Users can change the size and position of this PDFView. class ResizablePDFView: PDFView { override func draw(_ rect: CGRect) { super.draw(rect) } override func draw(_ layer: CALayer, in ctx: CGContext) { let isPDF = !UIGraphicsGetPDFContextBounds().isEmpty if isPDF { if let document = self.document, document.pageCount > 0, let page = document.page(at: 0) { ctx.saveGState() ctx.scaleBy(x: 1, y: -1) ctx.translateBy(x: 0, y: -bounds.size.height) let pageBounds = page.bounds(for: .mediaBox) ctx.scaleBy( x: bounds.size.width / pageBounds.size.width, y: bounds.size.height / pageBounds.size.height) ctx.translateBy(x: -pageBounds.origin.x, y: -pageBounds.origin.y) page.draw(with: .mediaBox, to: ctx) ctx.restoreGState() } }else { super.draw(layer, in: ctx) } } } class ResizableLabelView: UILabel { func setup() { self.font = UIFont.systemFont(ofSize: 20) self.textColor = UIColor.systemBlue } override func draw(_ rect: CGRect) { super.draw(rect) } override func draw(_ layer: CALayer, in ctx: CGContext) { let isPDF = !UIGraphicsGetPDFContextBounds().isEmpty if isPDF { draw(bounds) }else { super.draw(layer, in: ctx) } } } CanvasView setup, class ViewController: UIViewController { var canvasView: UIView! var pdfView: ResizablePDFView! var label: ResizableLabelView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. self.view.backgroundColor = UIColor.gray self.canvasView = UIView(frame: CGRect(origin: CGPoint.zero, size: CGSize(width: 400, height: 573))) self.canvasView.center = self.view.center self.canvasView.backgroundColor = UIColor.white self.view.addSubview(self.canvasView) self.setupPDF() self.setupLabel() } func setupPDF() { self.pdfView = ResizablePDFView(frame: CGRect(origin: .zero, size: self.canvasView.frame.size)) self.pdfView.backgroundColor = UIColor.clear self.canvasView.addSubview(self.pdfView) self.pdfView.autoScales = false self.pdfView.displayMode = .singlePage self.pdfView.displaysPageBreaks = false self.pdfView.pageBreakMargins = UIEdgeInsets.zero self.pdfView.pageShadowsEnabled = false if let file = Bundle.main.url(forResource: "sample_pdf", withExtension: "pdf") { if let pdfDocument = PDFDocument(url: file) { let pageNumber: Int = 0 if let page = pdfDocument.page(at: pageNumber) { let pageDocument = PDFDocument() pageDocument.insert(page, at: 0) self.pdfView.document = pageDocument self.pdfView.minScaleFactor = self.pdfView.scaleFactorForSizeToFit self.pdfView.maxScaleFactor = self.pdfView.scaleFactorForSizeToFit self.pdfView.scaleFactor = self.pdfView.scaleFactorForSizeToFit } } } } func setupLabel() { self.label = ResizableLabelView(frame: CGRect(x: 10, y: 10, width: 200, height: 50)) self.label.setup() self.label.text = "Sample Text" self.label.sizeToFit() self.canvasView.addSubview(self.label) } } now, I'm creating the PDF from canvasView @IBAction func exportButtonAction(_ sender: UIButton) { let filePath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("Exported_PDF.pdf") UIGraphicsBeginPDFContextToFile(filePath.path, .zero, [kCGPDFContextCreator as String: "PDF Export Demo App"]) guard let canvas = self.canvasView else { return } UIGraphicsBeginPDFPageWithInfo(canvas.bounds, nil) guard let context = UIGraphicsGetCurrentContext() else { return } canvas.setNeedsDisplay() canvas.layer.render(in: context) UIGraphicsEndPDFContext() print(filePath) } Now, This will render UILabel and UIImageView in PDF properly without rasterization and selectable text, but It does not draw PDFView like original pdf with links.
What am I doing wrong here? how can I debug this issue? https://drive.google.com/drive/folders/1qLcGNGWxoXbWJnr6xBxueKjPHnfxYS6D?usp=drive_link
0
0
333
Mar ’24
How to prepare PDF for digital certificate on iOS
I'm looking for guidance on how to prepare a PDF for inserting a digital certificate on iOS without a commercial 3rd party tool. The idea is to... Set up a signature annotation with PDFKit, Set up/prepare the PDF with the required information (contact info, adbe.pkcs7.detached, the Adobe.PPKLite filter , info/annotation reference, the UTC time, etc.) Pad the content area with zeros (I believe it would 4096 Then compute the hash. I am following Adobe's Spec (Acrobat_DigitalSignatures_in_PDF) Would this be possible with parsing out and adding the data from a byte stream? Can I simply build the signature object on my own and place them into the PDF, or are there any other items I need to change. Are there any tools out there that can help me manipulate the data and/or get the document hash easily? For example the data would look something like this is... <</ByteRange [0 552215 560537 907] /ContactInfo (my contact info)/Contents < AREA OF ZERO PADDING FOR CERT INSET) 00>/Filter /Adobe.PPKLite/M (D:20240223095734Z)/Reason (Some reason)/Reference [<</Data 13 0 R/TransformMethod/FieldMDP/TransformParams 39 0 R/Type/SigRef>>]/SubFilter /adbe.pkcs7.detached/Type /Sig>> Thank you
0
0
294
Feb ’24
PDFPage setBounds behaviour on cropBox differs on iPhone and iPad
I am trying to crop a pdf to remove 100 points from the top and bottom of the page. The mediaBounds of my pdf is size 612x792 and the origin is 0,0. My code the set the bounds of the cropBox is: page.setBounds(CGRect(origin: CGPointMake(0,100), size: CGSize(width: 612, height: 592)), for: .cropBox) This sets the origin at 0,100 and the cropBox size to be 200 less than the mediaBox size. This works on iPhone, but on iPad I need to set the height to be 692, otherwise too much is cropped. Is this a bug or is there an explanation?
0
0
262
Feb ’24
App running on iOS 17 creates different PDF data from on iOS 16 and earlier
Hello, I have a question about PDF data creation on iOS 17. My app creates PDF data from HTML for printing, and it is not possible to print out the PDF data to a particular printer when the app runs on iOS 17, despite that it works fine on iOS 16 and earlier. The cause of the printing problem is unclear, however, I found that the contents of PDF data are different between iOS 17 and iOS 16 in the following 4 points: PDF version iOS 17: Ver. 1.4 iOS 16: Ver. 1.3 Size of PDF data iOS 17: 100KB iOS 16: 505KB Embedded font iOS 17: HiraginoSans-W5 iOS 16: HiraginoSans-W3 Displayed text size iOS 17: just a little bigger than 14pt iOS 16: 14pt I am hoping that the printing problem can be resolved if my app running on iOS 17 creates the same PDF data as on iOS 16, so my question is: Is there any way to create the same format of PDF data as iOS 16 or earlier when an app is running on iOS 17, especially to create data in version 1.3 of PDF? In my app, I use almost the same as the following code to create PDF data from HTML, and I couldn't find any option to specify a version of PDF for UIPrintPageRenderer, UIMarkupTextPrintFormatter and UIGraphicsPDFContext classes... Any info would be appreciated. Thanks, let htmlString = """ <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=420,height=595, shrink-to-fit=yes" /> <style type="text/css"> * { box-sizing: border-box; font-family: 'Hiragino Mincho ProN', serif; font-size: 1em; line-height: 1; } body { margin: 0; padding: 0; font-size: 14pt; } span.gothic { font-size: 3.5em; font-family: "Helvetica Neue", Helvetica, "Hiragino Sans", sans-serif; } </style> </head> <body> 明朝体のテキスト <span class="gothic">ゴシック体のテキスト</span> </body> </html> """ let render = UIPrintPageRenderer() let paperRect = CGRect(x: 0, y: 0, width: 420.0, height: 595) // A5, 72 dpi render.setValue(paperRect, forKey: "paperRect") let contentsRect = CGRect(x: 0, y: 0, width: 420.0, height: 595) // A5, 72 dpi render.setValue(contentsRect, forKey: "printableRect") let fmt = UIMarkupTextPrintFormatter(markupText: htmlString) render.addPrintFormatter(fmt, startingAtPageAt: 0) let pdfData = NSMutableData() UIGraphicsBeginPDFContextToData(pdfData, paperRect, nil) render.prepare(forDrawingPages: NSMakeRange(0, render.numberOfPages)) let bound = UIGraphicsGetPDFContextBounds() for i in 0..<render.numberOfPages { UIGraphicsBeginPDFPage() render.drawPage(at: i, in: bound) } UIGraphicsEndPDFContext() do { let url = URL(fileURLWithPath:"test.pdf") try pdfData.write(to: url) print("Done") } catch { print("Failed to save", error) }
0
0
350
Feb ’24
Does UIGraphicsEndPDFContext flush and close the context file?
I'm getting infrequent crashes when I try to show a newly created PDF. The PDF is file based, and shortly after UIGraphicsEndPDFContext its shown. The crash reports make it appear that the file itself is being mutated after its displayed. So my question: is the file (self.filePath) absolutely flushed and closed when UIGraphicsEndPDFContext returns? If not, is there some way to detect when it has finished? Thanks! David `func addPageNumbers() { let url = URL(fileURLWithPath: filePath) guard let document = CGPDFDocument(url as CFURL) else { return } // You have to change the file path otherwise it can cause blank white pages to be drawn. self.filePath = "\(filePath)-final.pdf" UIGraphicsBeginPDFContextToFile(filePath, .zero, nil) let pageCount = document.numberOfPages for i in 1...pageCount { ... } } UIGraphicsEndPDFContext() }
1
0
364
Jan ’24