I have an app that can view a PDF that is already stored within the project. I want to be able to create a new PDF document and store it in the app directory to later view in the already existing viewer. The PDF would be created from an array var todoList: [String] = []
that is displayed on a UITableView
. I know to create a PDF, I have to create a file name, path, and directory. I don't know how to do this. I saw online reference to URL and URL request, but I'm not sure if this is the correct avenue for what I want to do. Can someone please give me some advice and guidance? Everything I can find is for Objective-C.
Asked
Active
Viewed 3.5k times
10

rmaddy
- 314,917
- 42
- 532
- 579

ChallengerGuy
- 2,385
- 6
- 27
- 43
-
Once you have the `NSData` for the PDF, use the methods of `NSData` to write the data to a path. – rmaddy Nov 03 '15 at 16:35
-
I have the NSData, but how do I write it to path as a PDF? – ChallengerGuy Nov 03 '15 at 16:40
-
Start by looking at the docs for `NSData` and find the methods used to write it to a file. – rmaddy Nov 03 '15 at 16:51
2 Answers
32
I used this code to create and save the file (using HTML)
func createPDF() {
let html = "<b>Hello <i>World!</i></b> <p>Generate PDF file from HTML in Swift</p>"
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: 0, y: 0, width: 595.2, height: 841.8) // A4, 72 dpi
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, .zero, nil)
for i in 1...render.numberOfPages {
UIGraphicsBeginPDFPage();
let bounds = UIGraphicsGetPDFContextBounds()
render.drawPage(at: i - 1, in: bounds)
}
UIGraphicsEndPDFContext();
// 5. Save PDF file
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
pdfData.write(toFile: "\(documentsPath)/file.pdf", atomically: true)
}
Then I loaded it into UIWebView
from the documents directory with this code:
func loadPDF(filename: String) {
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let url = URL(fileURLWithPath: documentsPath, isDirectory: true).appendingPathComponent(filename).appendingPathExtension("pdf")
let urlRequest = URLRequest(url: url)
webView.loadRequest(urlRequest)
}

bugloaf
- 2,890
- 3
- 30
- 49

Danny Narváez
- 576
- 5
- 10
-
You helped me with this and it was a big help. I have an incoming PDF now, that is being viewed from an `NSURL` that I want to save as a new PDF. I can't find anything on this for Swift 2. Can you please help? – ChallengerGuy Dec 22 '15 at 21:59
-
You should use [Alamofire](https://github.com/Alamofire/Alamofire#downloading-a-file) to download your PDF. – Danny Narváez Dec 24 '15 at 13:36
-
-
-
Perfect answer! How can I see this created pdf file on iBook or something? Why I'm asking because I'll use this pdf file later like attach e-mail or something else. Or any idea for sharing this pdf file. – coskukoz Nov 02 '16 at 08:59
-
1For working with email attachments you can use MFMailComposeViewController https://developer.apple.com/reference/messageui/mfmailcomposeviewcontroller, about iBooks here is a question you could guide http://stackoverflow.com/questions/26343420/open-local-pdf-file-in-ibooks – Danny Narváez Nov 02 '16 at 15:46
8
For Swift 3:
createPdf() {
// 1. Create Print Formatter with input text.
let formatter = UIMarkupTextPrintFormatter(markupText: textView.text)
// 2. Add formatter with pageRender
let render = UIPrintPageRenderer()
render.addPrintFormatter(formatter, startingAtPageAt: 0)
// 3. Assign paperRect and printableRect
let page = CGRect(x: 0, y: 0, width: 595.2, height: 841.8) // A4, 72 dpi
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 rect = CGRect.zero
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, rect, nil)
for i in 1...render.numberOfPages {
UIGraphicsBeginPDFPage();
let bounds = UIGraphicsGetPDFContextBounds()
render.drawPage(at: i - 1, in: bounds)
}
UIGraphicsEndPDFContext();
// 5. Save PDF file
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
pdfData.write(toFile: "\(documentsPath)/new.pdf", atomically: true)
print("saved success")
}