美文网首页iOS归纳
swift 5 创建 PDF 文件,并分享

swift 5 创建 PDF 文件,并分享

作者: 耽落 | 来源:发表于2019-11-07 10:35 被阅读0次

    使用 swift 5 ,把图片绘制到PDF上,形成pdf文件,并分享

    创建PDF

    方法一

    优点:可以在子线程中执行
    缺点:图片被垂直翻转,是由于UIKit和UIGraphics的绘图环境坐标原点不一样,一个在左上角,一个在左下角。所以你需要将图片垂直翻转一下再绘制。

        func method_1() {
           
            //准备绘制的图片数据
            let image = UIImage.init(named: "root")!
            //绘制的大小,让文件的每一页大小和图片的大小一致
            let imageRect = CGRect.init(origin: CGPoint.init(x: 0, y: 0), size: image.size)
            
            //进入准备工作
            
            //创建二进制流载体
            let pdfData = NSMutableData.init()
            //设置二进制文件载体
            UIGraphicsBeginPDFContextToData(pdfData, imageRect, nil)
            //获取上下文,“相当于画板”,必须要在 UIGraphicsBeginPDFContextToData 之后执行,否则绘制出来的文件是空白的
            let context = UIGraphicsGetCurrentContext()
            //开始一页的绘制
            UIGraphicsBeginPDFPage()
            
            //绘制 第一页
            context?.draw(image.cgImage!, in: imageRect)
            
            //开始下一页的绘制
            UIGraphicsBeginPDFPage()
            
            //绘制 第二页
            context?.draw(image.cgImage!, in: imageRect)
            
            //结束绘制
            UIGraphicsEndPDFContext()
            
            //获取沙箱路径
            let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last
            print(dir!)
            //URL 追加 文件名
            let path = dir?.appendingPathComponent("file.pdf")
            print(path!)
            do {
                //写文件到路径
                try pdfData.write(to: path!, options: .atomic)
            } catch {
                print("error catched")
            }
        }
    
    方法一优化版 -- 旋转了图片

    优点:图片是正向的,并且可以在子线程中执行

        func method_1_优化版() {
            //准备绘制的图片数据
            let image = UIImage.init(named: "icon_pencil")!
            //绘制的大小,让文件的每一页大小和图片的大小一致
            let imageRect = CGRect.init(origin: CGPoint.init(x: 0, y: 0), size: image.size)
            //图片垂直翻转重绘
            //开启绘制
            UIGraphicsBeginImageContextWithOptions(imageRect.size, false, 0)
            //垂直翻转
            let drawImage = UIImage.init(cgImage: image.cgImage!, scale: image.scale, orientation: .downMirrored)
            //绘制
            drawImage.draw(in: CGRect(origin: .zero, size: image.size))
            //获取翻转后的结果
            let newImage = UIGraphicsGetImageFromCurrentImageContext()!
            //结束绘制
            UIGraphicsEndImageContext()
            
            //进入准备工作
            
            //创建二进制流载体
            let pdfData = NSMutableData.init()
            //设置二进制文件载体
            UIGraphicsBeginPDFContextToData(pdfData, imageRect, nil)
            //获取上下文,“相当于画板”,必须要在 UIGraphicsBeginPDFContextToData 之后执行,否则绘制出来的文件是空白的
            let context = UIGraphicsGetCurrentContext()
            //开始一页的绘制
            UIGraphicsBeginPDFPage()
            
            //绘制 第一页
            context?.draw(newImage.cgImage!, in: imageRect)
            
            //开始下一页的绘制
            UIGraphicsBeginPDFPage()
            
            //绘制 第二页
            context?.draw(newImage.cgImage!, in: imageRect)
            
            //结束绘制
            UIGraphicsEndPDFContext()
            
            //获取沙箱路径
            let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last
            print(dir!)
            //URL 追加 文件名
            let path = dir?.appendingPathComponent("子线程.pdf")
            print(path!)
            do {
                //写文件到路径
                try pdfData.write(to: path!, options: .atomic)
            } catch {
                print("error catched")
            }
        }
    
    方法 2 :

    优点:使用控件做中间人,这样绘制的时候,图片会是正常的,而不是垂直翻转的
    缺点:是不能在子线程中使用

        func method_2() {
            
            //准备绘制的图片数据
            let image = UIImage.init(named: "root")!
            //使用控件做中间人,这样绘制的时候,图片会是正常的,而不是垂直翻转的
            let imageView = UIImageView.init(image: image)
            
            //绘制的大小,让文件的每一页大小和图片的大小一致
            let imageRect = CGRect.init(origin: CGPoint.init(x: 0, y: 0), size: image.size)
            
            //进入准备工作
            
            //创建二进制流载体
            let pdfData = NSMutableData.init()
            //设置二进制文件载体
            UIGraphicsBeginPDFContextToData(pdfData, imageRect, nil)
            //获取上下文,“相当于画板”,必须要在 UIGraphicsBeginPDFContextToData 之后执行,否则绘制出来的文件是空白的
            let context = UIGraphicsGetCurrentContext()
            //开始一页的绘制
            UIGraphicsBeginPDFPage()
            
            //绘制 第一页
            imageView.layer.render(in: context!)
            
            //开始下一页的绘制
            UIGraphicsBeginPDFPage()
            
            //绘制 第二页
            imageView.layer.render(in: context!)
            
            //结束绘制
            UIGraphicsEndPDFContext()
            
            //获取沙箱路径
            let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last
            print(dir!)
            //URL 追加 文件名
            let path = dir?.appendingPathComponent("file.pdf")
            print(path!)
            do {
                //写文件到路径
                try pdfData.write(to: path!, options: .atomic)
            } catch {
                print("error catched")
            }
        }
    
    方法三

    个人对于这个绘制流程不是太清楚,没有研究怎么去多页绘制

        func method_3() {
            //准备绘制的图片数据
            let image = UIImage.init(named: "root")!
            //绘制的大小,让文件的每一页大小和图片的大小一致
            var imageRect = CGRect.init(origin: CGPoint.init(x: 0, y: 0), size: image.size)
            
            //创建二进制流载体
            let pdfData = NSMutableData.init()
            
            let pdfConsumer = CGDataConsumer.init(data: pdfData)!
            
            let pdfContext = CGContext.init(consumer: pdfConsumer, mediaBox: &imageRect, nil)
            
    //        pdfContext?.beginPDFPage(T##pageInfo: CFDictionary?##CFDictionary?)
            pdfContext?.beginPage(mediaBox: &imageRect)
            pdfContext?.draw(image.cgImage!, in: imageRect)
            pdfContext?.endPage()
            
            //获取沙箱路径
            let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last
            print(dir!)
            //URL 追加 文件名
            let path = dir?.appendingPathComponent("file.pdf")
            print(path!)
            do {
                //写文件到路径
                try pdfData.write(to: path!, options: .atomic)
            } catch {
                print("error catched")
            }
        }
    

    分享PDF文件

    这里使用的是IOS的原生分享 UIActivityViewController,在上面创建PDF文件的时候 ,已经拿到了文件路径‘ filePath’和二进制数据‘ pDFData’,这里直接使用

    //获取分享
    let activityController = UIActivityViewController.init(activityItems: [pDFData, filePath], applicationActivities: nil)
                    
    activityController.completionWithItemsHandler = {
        activity, success, items, errot in
        //为了不使得我们的应用占用更多的手机内存空间,我们分享之后,则把文件删除
        try! FileManager.default.removeItem(at: filePath)
    }
    self.present(activityController, animated: true, completion: { print("弹窗结束")})
    

    相关文章

      网友评论

        本文标题:swift 5 创建 PDF 文件,并分享

        本文链接:https://www.haomeiwen.com/subject/jgpmbctx.html