使用 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("弹窗结束")})
网友评论