TPPDF is a PDF builder for iOS, based on the Builder pattern using simple commands.
- ✅ Page header and footer
- ✅ Dynamic content layout with page alignment
- ✅ Support for tables and cell alignment
- ✅ Attributed strings
- ✅ Custom spacing
- ✅ Image support
- ✅ Horizontal line separators
- ✅ Custom indentation
- ✅ Custom top offset (good for layered rendering)
- ✅ Pagination
- ✅ Image caption
- ✅ Compress images
- ✅ Custom image size fit
- ✅ Image in the header and footer
- ✅ Horizontal line separators in the header and footer
- ✅ Generate PDF files directly to handle large PDF files (Details)
- ✅ PDF metadata
- You need more features? Checkout #Contribute
Language | Branch | Pod version | Xcode version | iOS version |
---|---|---|---|---|
Swift 3.0 | master | >= 0.2.x | Xcode 8 or greater | iOS 8.0+ |
Swift 2.3 | swift-2.3 | 0.1.5 | Xcode 8, Xcode 7.3.x | iOS 8.0+ |
Swift 2.2 | swift-2.2 | 0.1.4 | Xcode 7.3.x | iOS 8.0+ |
To run the example project, clone the repo, and run pod install
from the Example directory first.
If you want to see a fully working example, please try the Cocoapod using pod try TPPDF
.
TPPDF creates a PDF based on commands. When the generator starts to build the PDF file it calls one command after another, until no commands are left.
Currently the following commands exist:
addText(...)
addAttributedText(...)
addImage(...)
addSpace(...)
addLineSeparator(...)
addTable(...)
addImagesInRow(...)
setIndentation(...)
setAbsoluteOffset(...)
resetFont(...)
createNewPage()
Every command is associated to a specific container. Three containers exist: Header, Content, Footer. Additionally every container has an alignment: Left, Center, Right.
When registering a command you provide the correct container - the default container is ContentLeft
. When the PDFGenerator performs the commands, it applies the to the correct container. This way you can identify which area of the PDF gets changed.
A good example would be the following call:
let pdf = PDFGenerator(format: .a4)
pdf.addText(.footerCenter, text: "Created using TPPDF for iOS.")
This command adds the text "Created using TPPDF for iOS" to the footer of all pages.
The following values can be set to format the page:
pageBounds
pageMargin
headerMargin
footerMargin
headerSpace
footerSpace
All values are in dots and are rendered using 72 DPI (dots per inch), as this is the default screen DPI.
You can also used the predefined formats. For details please refer to the source file PageFormat.swift
If you want to add a text to the header or footer you simply need to choose the correct container.
If you want to render an image in one of these containers, it will use the square size headerImageHeight
.
But there are some limitations:
- Only one line. If you want multiple lines, add multiple commands
To enable pagination, set a Container
on the variable paginationContainer
.
To reduce the amount of data and the resulting file size, you can reduce the image quality by setting a value between 0 and 1 on the variable imageQuality
.
Configure PDF metadata, including title
, author
, subject
, keywords
, owner password
, user password
, allows printing
, and allows copying
.
The following commands are the ones available to you for creating your document. Most of these take a container as a parameter, defaulting to page content with left alignment. For the sake of readability, there is only a container in the example of addText(...)
.
Draws a text in the given container. It creates a attributed string and sets the linespacing.
Example:
pdf.addText(.ContentCenter, text: "Created using TPPDF for iOS.", lineSpacing: 5)
Draws a NSAttributedString in the given container.
Example:
let title = NSMutableAttributedString(string: "Awesome attributed title!", attributes: [
NSFontAttributeName : UIFont.systemFontOfSize(28.0),
NSForegroundColorAttributeName : UIColor(red: 219.0 / 255.0, green: 100.0 / 255.0, blue: 58.0 / 255.0, alpha: 1.0)
])
pdf.addAttributedText(text: title)
Draws an image in the given container. If the given size is not zero size, it will draw it using that size, proportionally scaling. The size of an image is scaled according to sizeFit. If the height of an image and its caption is beyond the page bounds, then a new page is created. The caption is an attributed string and can be styled (refer to addAttributedText(...)
for an example).
Example:
pdf.addImage(image: UIImage(named: "Image.jpg")!)
Adds the given value to the content height, resulting in a space between the previous and the next command element.
Example:
pdf.addSpace(space: 12.0)
Draws a horizontal line using the given line thickness and color in the given container.
Example:
pdf.addLineSeparator(thickness: 0.1, color: UIColor.lightGrayColor())
addTable(container, data, alignment, relativeColumnWidth, padding, margin, textColor, lineColor, lineWidth, drawCellBounds, textFont)
Draws a table in the given container.
The parameter data is a two-dimensional String array
let data: [[String]] = [
["Rating", "4.5 / 5", "Prep\nTime:", "14 Hours" ],
["Portions:", "14", "Cook\nTime:", "16 Minutes", ]
]
The parameter alignment is a two-dimensional array with TableCellAlignment
values.
let alignments: [[TableCellAlignment]] = [
[.Left, .Center, .Left, .Center],
[.Left, .Center, .Left, .Center]
]
The parameter relativeColumnWidth
is an array of CGFloat smaller or equal than 1.0
These are relative widths in percentage to the full page content width (= page width - 2 * page margin). It defines the width of each column.
let widths: [CGFloat] = [
0.3, 0.2, 0.3, 0.2
]
The data array and the alignments array must contain the equal amount of items. The widths array must have the same amount as the data array columns has.
Additional parameters are cell margin and cell padding. Margin is the spacing between each cell or between the cell and the table bounds. Padding is the spacing between the content of the cell to the cell bounds.
This works the same way as HTML/CSS margin and padding works. Checkout w3schools.com margin and padding
Next to the text color, you can also set the line color and the line width.
The parameter drawCellBounds is a Boolean parameter, deciding if the cell bounds are drawn. The cell bounds are not the row/column grid of the table, but the lines between cell margin and cell padding. w3schools.com explains it
Example:
pdf.addTable(data: tableData, alignment: tableAlignment, relativeColumnWidth: tableWidth, padding: 5, margin: 5, textColor: UIColor.blackColor(), lineColor: UIColor.darkGrayColor(), lineWidth: 1.5, drawCellBounds: false)
Draws images with captions in the row using the given spacing in the given container.
Example:
pdf.addImagesInRow(images: [UIImage(named: "image.jpg")!, UIImage(named: "PortraitImage.jpg")!], captions: [NSAttributedString(string: "Caption 1"), NSAttributedString(string: "Caption 2")])
If you need to indent your content you can simply call this method.
Example:
pdf.setIndentation(indent: 50.0)
Now add more commands which are indented.
If you need to reset the indentation simply call the function with 0.0
as parameter
Example:
pdf.setIndentation(indent: 0.0)
If you do not want to add a space between two elements, you can also set a absolut offset form the top border.
One possible use case are layered PDF files.
Simply call pdf.setOffset(offset: 0.0)
and you can add content which is placed on top of the previously set content.
Example:
pdf.setOffset(offset: 250.0)
Sets the font of a container. This font will be used in the next commands in the given container, if there is not a different font specified.
Example:
pdf.setFont(UIFont.systemFont(ofSize: 20.0))
This resets the font to the default font, which is UIFont.systemFont(ofSize: UIFont.systemFontSize)
Example:
pdf.resetFont(.contentLeft)
Create a new page.
pdf.createNewPage()
- If you need help, use Stack Overflow. (Tag 'TPPDF')
- If you'd like to ask a general question, use Stack Overflow.
- If you found a bug, open an issue.
- If you have a feature request, open an issue.
- If you want to contribute, submit a pull request.
You need more commands? Just fork the project, implement the following and create a pull request!
To implement a new command you need to edit the following places. As an example we implement the command SetFont
:
- Add
SetFont
to the enumCommand
in Command.swift
enum Command {
...
case SetFont(font: UIFont)
}
- Add
SetFont
to the switch statement in the methodrenderCommand
in PDFGenerator.swift. In this case you do not need to create anotherdraw...
method but in other cases you might have to create a new private drawing method, handling different containers.
switch command {
...
case let .SetFont(font):
self.font = font // Currently there is one font variable used for draw calls. If you change it, all future commands will use the new font.
break
}
}
- Add a public method
setFont
which adds a command to the command chain.
public func setFont(container: Container = Container.ContentLeft, font: UIFont = UIFont.systemFontOfSize(14)) {
commands += [(container, .SetFont(font: font))]
}
If you add default values, then you need to do it in this method!
The previous example does not handle different Containers
. The correct way of doing this, would be three instance variables of type UIFont
. One for the header, one for the content and one for the footer.
Then, when calling the command, it changes the correct font variable, depending on the Container provided.
CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:
$ gem install cocoapods
To integrate TPPDF into your Xcode project using CocoaPods, specify it in your Podfile
:
target '<Your Target Name>' do
pod 'TPPDF'
end
Then, run the following command:
$ pod install
Not supported yet. Please refer to Issue #2
If you prefer not to use either of the aforementioned dependency managers, you can integrate TPPDF into your project manually.
- Open up Terminal,
cd
into your top-level project directory, and run the following command "if" your project is not initialized as a git repository:
$ git init
- Add TPPDF as a git submodule by running the following command:
$ git submodule add https://github.com/Techprimate/TPPDF.git
-
Open the new
TPPDF
folder, and drag theTPPDF.xcodeproj
into the Project Navigator of your application's Xcode project.It should appear nested underneath your application's blue project icon. Whether it is above or below all the other Xcode groups does not matter.
-
Select the
TPPDF.xcodeproj
in the Project Navigator and verify the deployment target matches that of your application target. -
Next, select your application project in the Project Navigator (blue project icon) to navigate to the target configuration window and select the application target under the "Targets" heading in the sidebar.
-
In the tab bar at the top of that window, open the "General" panel.
-
Click on the
+
button under the "Embedded Binaries" section. -
You will see two different
TPPDF.xcodeproj
folders each with two different versions of theTPPDF.framework
nested inside aProducts
folder.It does not matter which
Products
folder you choose from, but it does matter whether you choose the top or bottomTPPDF.framework
. -
Select the top
TPPDF.framework
for iOS and the bottom one for OS X.You can verify which one you selected by inspecting the build log for your project. The build target for
TPPDF
will be listed as eitherTPPDF iOS
orTPPDF OSX
. -
And that's it!
The
TPPDF.framework
is automagically added as a target dependency, linked framework and embedded framework in a copy files build phase which is all you need to build on the simulator and a device.
If you are using TPPDF in your app and want to be listed here, simply create a pull request or let me know on twitter or via github. I am always curious who is using my projects :)
Hikingbook - by Zheng-Xiang Ke
Mama's Cookbook (future release) - by Philip Niedertscheider
TPPDF is created by Philip Niedertscheider.
Special thanks goes to Nutchaphon Rewik for his project SimplePDF for the inspiration and code base.
- Philip Niedertscheider, techprimate
- Zheng-Xiang Ke, kf99916
TPPDF is available under the MIT license. See the LICENSE file for more info.