最近有个项目,功能为将多张图片创建为PDF
文件。
创建PDF
文档在iOS
中有两种方法
PDFKit
UIKit -> UIGraphicsPDFRenderer
PDFKit
在 iOS 11
版本之后,iOS
提供了生成与预览 PDF
文件的框架,即为 PDFKit
。本篇文章不讨论使用 PDFKit
预览 PDF
文档的功能( PDFView
)。感兴趣的同学可以自己去看看,不难。
PDFKit
提供了大量的类
PDFDocument
:描述为整个PDF文档,用于生成或获取PDF文档PDFPage
:PDF的页PDFAction
: 点击PDF的事件,基本使用其子类完成相关点击动作,如点击链接(PDFActionURL
)。点击名称(PDFActionName
)等。PDFAnnotation
: PDF的注释,如向PDF的某一处添加一段文字。PDFKit
在生成文档时只要使用了两个类 PDFDocument
、PDFPage
。
废话不多说,上代码
/// - Parameters:
/// - url: 创建PDF的根路径
/// - name: PDF文件名称
/// - images: 图片列表
/// - completed: 返回
func convertPDF(url: URL, name: String, images: [UIImage], completed: @escaping (String) -> Void) {
var path = url.appendingPathComponent(name).appendingPathExtension("pdf")
var number = 0
// 防止重名
while self.isExist(path: path.path) {
number += 1
path = url.appendingPathComponent(name + "(\(number))")
.appendingPathExtension("pdf")
}
let queue = DispatchQueue(label: "com.create.pdf")
queue.async {
let pdfDocument = PDFDocument()
for (index, image) in images.enumerated() {
// 创建页
let pdfPage = PDFPage(image: image)
// 设置页面大小
pdfPage?.setBounds(CGRect(origin: .zero, size: PDFSettingState.shared.size), for: .mediaBox)
// 添加页
pdfDocument.insert(pdfPage!, at: index)
}
pdfDocument.write(to: path)
// 加密PDF文档
// pdfDocument.write(to: path, withOptions: [.ownerPasswordOption: "123456"])
DispatchQueue.main.async {
completed(path.path)
}
}
}
UIImageView
的 UIViewContentModeScaleAspectFill
方式。UIKit
如果项目需要适配 iOS 11
以下的系统版本,那么就只能使用 UIGraphicsPDFRendererFormat
进行 PDF
创建了。
上代码
/// - Parameters:
/// - url: 创建PDF的根路径
/// - name: PDF文件名称
/// - images: 图片列表
/// - completed: 返回
func createPDF(url: URL, name: String, images: [UIImage], completed: @escaping (String) -> Void) {
var path = url.appendingPathComponent(name).appendingPathExtension("pdf")
var number = 0
// 防止重名
while self.isExist(path: path.path) {
number += 1
path = url.appendingPathComponent(name + "(\(number))")
.appendingPathExtension("pdf")
}
let queue = DispatchQueue(label: "com.create.pdf")
queue.async {
// 纸张大小
let rect = PDFSettingState.shared.getSize()
var pdfInfo = [String: Any]()
// 加密
if !PDFSettingState.shared.password.isEmpty {
pdfInfo[kCGPDFContextOwnerPassword as String] = PDFSettingState.shared.password
}
let format = UIGraphicsPDFRendererFormat()
format.documentInfo = pdfInfo
let render = UIGraphicsPDFRenderer(bounds: rect, format: format)
let data = render.pdfData { context in
var x: CGFloat = 0
for image in images {
// 开启PDF中的一页
context.beginPage()
if image.size.width <= rect.size.width {
x = (rect.size.width - image.size.width) / 2.0
} else {
x = 0
}
image.draw(at: CGPoint(x: x, y: 0))
}
}
UIGraphicsEndPDFContext()
try! data.write(to: path)
DispatchQueue.main.async {
completed(path.path)
}
}
}
UIImageView
的 UIViewContentModeScaleAspectFill
方式。由于网上的文档多数都有问题,没办法只能自己看官方文档以及代码进行学习。相比较而言,PDFKit
要比 UIKit
的使用方式要简单一点,但功能也要简单一点。最起码无法设置纸张大小,也许是因为图片大小不符合纸张大小而不成功吧。这个问题就交给大家了。
最后附上纸张大小的尺寸网址 Paper Sizes。