How to create a PDF file in Swift using Cocoa (Mac)

Xcode 7.3.2, Swift 2, Cocoa (Mac).

My application includes a user who enters text that can be exported to a PDF file.

In the version of my iOS application, I can easily create a PDF using the CoreText framework:

 let html = "<font face=\'Futura\' color=\"SlateGray\"><h2>\(title)</h2></font><font face=\"Avenir\" color=\"SlateGray\"><h4>\(string)</h4></font>" let fmt = UIMarkupTextPrintFormatter(markupText: html) // 2. Assign print formatter to UIPrintPageRenderer let render = UIPrintPageRenderer() render.addPrintFormatter(fmt, startingAtPageAt: 0) // 3. Assign paperRect and printableRect let page = CGRect(x: 10, y: 10, width: 595.2, height: 841.8) // A4, 72 dpi, margin of 10 from top and left. let printable = page.insetBy(dx: 0, dy: 0) render.setValue(NSValue(cgRect: page), forKey: "paperRect") render.setValue(NSValue(cgRect: printable), forKey: "printableRect") // 4. Create PDF context and draw let pdfData = NSMutableData() UIGraphicsBeginPDFContextToData(pdfData, CGRect.zero, nil) for i in 1...render.numberOfPages { UIGraphicsBeginPDFPage(); let bounds = UIGraphicsGetPDFContextBounds() render.drawPage(at: i - 1, in: bounds) } UIGraphicsEndPDFContext(); // 5. Save PDF file path = "\(NSTemporaryDirectory())\(title).pdf" pdfData.write(toFile: path, atomically: true) 

However, UIMarkupTextPrintFormatter , UIPrintPageRenderer , UIGraphicsBeginPDFContextToData and UIGraphicsEndPDFContext all do not exist on OS X. How can I do the same thing as me with this iOS code (create a basic PDF file from some HTML and write it to a specific file path PDF) with Mac and Cocoa?

EDIT: The answer to this question is here: Create paginated PDF-Mac OS X.

+6
source share
1 answer

Here is a function that will generate PDF from pure HTML.

 func makePDF(markup: String) { let directoryURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] let printOpts: [NSPrintInfo.AttributeKey: Any] = [NSPrintInfo.AttributeKey.jobDisposition: NSPrintInfo.JobDisposition.save, NSPrintInfo.AttributeKey.jobSavingURL: directoryURL] let printInfo = NSPrintInfo(dictionary: printOpts) printInfo.horizontalPagination = NSPrintingPaginationMode.AutoPagination printInfo.verticalPagination = NSPrintingPaginationMode.AutoPagination printInfo.topMargin = 20.0 printInfo.leftMargin = 20.0 printInfo.rightMargin = 20.0 printInfo.bottomMargin = 20.0 let view = NSView(frame: NSRect(x: 0, y: 0, width: 570, height: 740)) if let htmlData = markup.dataUsingEncoding(NSUTF8StringEncoding) { if let attrStr = NSAttributedString(HTML: htmlData, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil) { let frameRect = NSRect(x: 0, y: 0, width: 570, height: 740) let textField = NSTextField(frame: frameRect) textField.attributedStringValue = attrStr view.addSubview(textField) let printOperation = NSPrintOperation(view: view, printInfo: printInfo) printOperation.showsPrintPanel = false printOperation.showsProgressPanel = false printOperation.run() } } } 

What's happening:

  • Put HTML in NSAttributedString.
  • Map NSAttributedString to NSTextField.
  • Display NSTextField for NSView.
  • Create an NSPrintOperation using this NSView.
  • Set the print options to save as PDF.
  • Run the print operation (which actually opens a dialog box for saving the PDF file).
  • Everyone is happy.

This is not an ideal solution. Note the hard coded integer value.

+4
source

All Articles