iOS归纳

swift 5 创建 PDF 文件,并分享

2019-11-07  本文已影响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("弹窗结束")})
上一篇下一篇

猜你喜欢

热点阅读