I would like to create a PDF from a UITableView in Swift. Ill found some tutorials for Objective C, and tried it out but there is still no file generated by this code.
// get a temprorary filename for this PDF
var path = NSTemporaryDirectory();
var pdfFilePath = path.stringByAppendingPathComponent("mypdfdocument.pdf")
UIGraphicsBeginPDFContextToFile(pdfFilePath, CGRectMake(0, 0, self.tableView.contentSize.width, self.tableView.contentSize.height), nil)
UIGraphicsBeginPDFPage();
self.view.layer.renderInContext(UIGraphicsGetCurrentContext())
self.tableView.scrollRectToVisible(CGRectMake(0, 0, 1, 1), animated: false)
self.tableView.layer.renderInContext(UIGraphicsGetCurrentContext())
var screensInTable = Int(self.tableView.contentSize.width) / Int(self.tableView.contentSize.height)
for i in 1...screensInTable {
var point = CGFloat(CGFloat(i) * self.tableView.bounds.height)
var contentOffset:CGPoint = CGPointMake(0, point)
self.tableView.setContentOffset(contentOffset, animated: false)
self.tableView.layer.renderInContext(UIGraphicsGetCurrentContext())
}
UIGraphicsEndPDFContext();
And: I have a Table with 4 Sections and different Row Heights and Cell Templates. Is there a Chance that the generated PDF easily with this type of code? Or would it be better to create Row by Row with CoreText?
Thanks in advance.
In the project choose File ▸ New ▸ File… and select the iOS ▸ Cocoa Touch Class template. Then, click Next. Once you've done that, name the class PDFCreator and make it a subclass of NSObject. Ensure the Language is set to Swift.
First Create a project from Xcode. File ▸ New ▸ Project…. Choose the iOS ▸ Application ▸ Single View App template and create a new project. Then create a PDFCreator class where we will add all functions and variables which helps us to create the PDF.
Here is my approach. Use a template view. It has all the static texts and images. And then for every page in pdf use this template view. Here is the function that I use:
func renderAsPDF(demandEntry: ParsedDemandEntry, inView view: UIView) -> NSData? {
let entries = demandEntry.demands
let pageCount = Int(ceil(Double(entries.count) / Double(demandCountForPage)))
if pageCount != 0 {
let views = (1...pageCount).map { (pageNumber: Int) -> UIView in
let pdfPageView = createTemplatePageViewWithParsedEntry(demandEntry, inView: view)
let pageRange = ((pageNumber - 1) * demandCountForPage)..<(min(pageNumber * demandCountForPage, entries.count))
let entriesForPage = Array(entries[pageRange])
addEntries(entriesForPage, toView: pdfPageView)
pdfPageView.removeFromSuperview()
return pdfPageView
}
return toPDF(views)
} else {
return nil
}
}
The ParsedDemandEntry
is my model object. The view
parameter is a container view to prepare pdf view in it. This is necessary because I use auto layout to position all labels in pdf view. Without a super view layout process won't work.
Let's walk into function. First I get entries from model object. Think these are rows that needs to populate in pdf. After that I calculate how many pages I need. Then the loop begins. In every loop I create a tamplate view. (pdfPageView
). And then fill it with entries. (addEntries(_:toView:)
function call).
After the loop I give all views to toPDF
function. It creates NSData
that represents pdf. Here is how toPDF
function look like:
private func toPDF(views: [UIView]) -> NSData? {
if views.isEmpty {
return nil
}
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, CGRect(x: 0, y: 0, width: 612, height: 792), nil)
let context = UIGraphicsGetCurrentContext()
for view in views {
UIGraphicsBeginPDFPage()
view.layer.renderInContext(context)
}
UIGraphicsEndPDFContext()
return pdfData
}
It is fairly simple. First I create pdf context. And then loop through views
array. For each view It renders view into pdf context.
I hope this will help.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With