• iOS 创建PDF文件


    前言

    最近有个项目,功能为将多张图片创建为PDF文件。

    创建PDF文档在iOS中有两种方法

    1. PDFKit
    2. 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在生成文档时只要使用了两个类 PDFDocumentPDFPage

    废话不多说,上代码

        /// - 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)
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    缺陷

    • 固定大小之后图片会失真,图片变得发白
    • 如果图片与所设定的尺寸不一致时,图片将会自适应纸张大小,类似 UIImageViewUIViewContentModeScaleAspectFill 方式。

    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)
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    缺陷

    • 图片会自适应纸张大小,类似 UIImageViewUIViewContentModeScaleAspectFill 方式。

    总结

    由于网上的文档多数都有问题,没办法只能自己看官方文档以及代码进行学习。相比较而言,PDFKit 要比 UIKit 的使用方式要简单一点,但功能也要简单一点。最起码无法设置纸张大小,也许是因为图片大小不符合纸张大小而不成功吧。这个问题就交给大家了。

    最后附上纸张大小的尺寸网址 Paper Sizes

  • 相关阅读:
    卷土重来?东山再起?不,C语言一直是王者
    C++类和对象(三)
    关于并发和并行,Go和Erlang之父都弄错了?
    Java学习笔记4.2.2 系统类 - Runtime类
    大健康行业千城万企信用建设工作启动大会在京召开
    Enzo蛋白聚集分析试剂盒——快速、特异性和定量标记
    使用idea创建第一个springboot项目
    PostgreSQL的学习心得和知识总结(一百一十二)|语法级自上而下完美实现PostgreSQL数据库的 EXCHANGE PARTION 的实现方案
    超详细Redis入门教程三
    java面试强基(4)
  • 原文地址:https://blog.csdn.net/LiqunZhang/article/details/127554582