版本记录
版本号 | 时间 |
---|---|
V1.0 | 2019.09.16 星期一 |
前言
今天翻阅苹果的API文档,发现多了一个框架就PDFKit,看了下才看见是iOS11.0新添加的框架,这里我们就一起来看一下框架PDFKit。感兴趣的可以看下面几篇文章。
1. PDFKit框架详细解析 (一) —— 基本概览(一)
2. PDFKit框架详细解析 (二) —— 基于PDFKit的PDF文档的创建和分享(一)
源码
1. Swift
首先看下工程组织结构
下面就看一下sb中的内容
下面就是代码了
1. PDFPreviewViewController.swift
import UIKit
import PDFKit
class PDFPreviewViewController: UIViewController {
public var documentData: Data?
@IBOutlet weak var pdfView: PDFView!
override func viewDidLoad() {
super.viewDidLoad()
if let data = documentData {
pdfView.document = PDFDocument(data: data)
pdfView.autoScales = true
}
}
}
2. FlyerBuilderViewController.swift
import UIKit
class FlyerBuilderViewController: UIViewController {
@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var flyerTextEntry: UITextField!
@IBOutlet weak var bodyTextView: UITextView!
@IBOutlet weak var contactTextView: UITextView!
@IBOutlet weak var imagePreview: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Add subtle outline around text views
bodyTextView.layer.borderColor = UIColor.gray.cgColor
bodyTextView.layer.borderWidth = 1.0
bodyTextView.layer.cornerRadius = 4.0
contactTextView.layer.borderColor = UIColor.gray.cgColor
contactTextView.layer.borderWidth = 1.0
contactTextView.layer.cornerRadius = 4.0
// Add the share icon and action
let shareButton = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(shareAction))
self.toolbarItems?.append(shareButton)
// Add responder for keyboards to dismiss when tap or drag outside of text fields
scrollView.addGestureRecognizer(UITapGestureRecognizer(target: scrollView, action: #selector(UIView.endEditing(_:))))
scrollView.keyboardDismissMode = .onDrag
}
@objc func shareAction() {
// 1
guard
let title = flyerTextEntry.text,
let body = bodyTextView.text,
let image = imagePreview.image,
let contact = contactTextView.text
else {
// 2
let alert = UIAlertController(title: "All Information Not Provided", message: "You must supply all information to create a flyer.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(alert, animated: true, completion: nil)
return
}
// 3
let pdfCreator = PDFCreator(title: title, body: body, image: image, contact: contact)
let pdfData = pdfCreator.createFlyer()
let vc = UIActivityViewController(activityItems: [pdfData], applicationActivities: [])
present(vc, animated: true, completion: nil)
}
@IBAction func selectImageTouched(_ sender: Any) {
let actionSheet = UIAlertController(title: "Select Photo", message: "Where do you want to select a photo?", preferredStyle: .actionSheet)
let photoAction = UIAlertAction(title: "Photos", style: .default) { (action) in
if UIImagePickerController.isSourceTypeAvailable(.savedPhotosAlbum) {
let photoPicker = UIImagePickerController()
photoPicker.delegate = self
photoPicker.sourceType = .photoLibrary
photoPicker.allowsEditing = false
self.present(photoPicker, animated: true, completion: nil)
}
}
actionSheet.addAction(photoAction)
let cameraAction = UIAlertAction(title: "Camera", style: .default) { (action) in
if UIImagePickerController.isSourceTypeAvailable(.camera) {
let cameraPicker = UIImagePickerController()
cameraPicker.delegate = self
cameraPicker.sourceType = .camera
self.present(cameraPicker, animated: true, completion: nil)
}
}
actionSheet.addAction(cameraAction)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
actionSheet.addAction(cancelAction)
self.present(actionSheet, animated: true, completion: nil)
}
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
if
let _ = flyerTextEntry.text,
let _ = bodyTextView.text,
let _ = imagePreview.image,
let _ = contactTextView.text {
return true
}
let alert = UIAlertController(title: "All Information Not Provided", message: "You must supply all information to create a flyer.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(alert, animated: true, completion: nil)
return false
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "previewSegue" {
guard let vc = segue.destination as? PDFPreviewViewController else { return }
if let title = flyerTextEntry.text, let body = bodyTextView.text,
let image = imagePreview.image, let contact = contactTextView.text {
let pdfCreator = PDFCreator(title: title, body: body,
image: image, contact: contact)
vc.documentData = pdfCreator.createFlyer()
}
}
}
}
extension FlyerBuilderViewController: UIImagePickerControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
guard let selectedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else {
return
}
imagePreview.image = selectedImage
imagePreview.isHidden = false
dismiss(animated: true, completion: nil)
}
}
extension FlyerBuilderViewController: UINavigationControllerDelegate {
// Not used, but necessary for compilation
}
3. PDFCreator.swift
import UIKit
import PDFKit
class PDFCreator: NSObject {
let title: String
let body: String
let image: UIImage
let contactInfo: String
init(title: String, body: String, image: UIImage, contact: String) {
self.title = title
self.body = body
self.image = image
self.contactInfo = contact
}
func createFlyer() -> Data {
// 1
let pdfMetaData = [
kCGPDFContextCreator: "Flyer Builder",
kCGPDFContextAuthor: "raywenderlich.com",
kCGPDFContextTitle: title
]
let format = UIGraphicsPDFRendererFormat()
format.documentInfo = pdfMetaData as [String: Any]
// 2
let pageWidth = 8.5 * 72.0
let pageHeight = 11 * 72.0
let pageRect = CGRect(x: 0, y: 0, width: pageWidth, height: pageHeight)
// 3
let renderer = UIGraphicsPDFRenderer(bounds: pageRect, format: format)
// 4
let data = renderer.pdfData { (context) in
// 5
context.beginPage()
// 6
let titleBottom = addTitle(pageRect: pageRect)
let imageBottom = addImage(pageRect: pageRect, imageTop: titleBottom + 18.0)
addBodyText(pageRect: pageRect, textTop: imageBottom + 18.0)
let context = context.cgContext
drawTearOffs(context, pageRect: pageRect, tearOffY: pageRect.height * 4.0 / 5.0, numberTabs: 8)
drawContactLabels(context, pageRect: pageRect, numberTabs: 8)
}
return data
}
func addTitle(pageRect: CGRect) -> CGFloat {
// 1
let titleFont = UIFont.systemFont(ofSize: 18.0, weight: .bold)
// 2
let titleAttributes: [NSAttributedString.Key: Any] =
[NSAttributedString.Key.font: titleFont]
let attributedTitle = NSAttributedString(string: title, attributes: titleAttributes)
// 3
let titleStringSize = attributedTitle.size()
// 4
let titleStringRect = CGRect(x: (pageRect.width - titleStringSize.width) / 2.0,
y: 36, width: titleStringSize.width,
height: titleStringSize.height)
// 5
attributedTitle.draw(in: titleStringRect)
// 6
return titleStringRect.origin.y + titleStringRect.size.height
}
func addBodyText(pageRect: CGRect, textTop: CGFloat) {
// 1
let textFont = UIFont.systemFont(ofSize: 12.0, weight: .regular)
// 2
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .natural
paragraphStyle.lineBreakMode = .byWordWrapping
// 3
let textAttributes = [
NSAttributedString.Key.paragraphStyle: paragraphStyle,
NSAttributedString.Key.font: textFont
]
let attributedText = NSAttributedString(string: body, attributes: textAttributes)
// 4
let textRect = CGRect(x: 10, y: textTop, width: pageRect.width - 20,
height: pageRect.height - textTop - pageRect.height / 5.0)
attributedText.draw(in: textRect)
}
func addImage(pageRect: CGRect, imageTop: CGFloat) -> CGFloat {
// 1
let maxHeight = pageRect.height * 0.4
let maxWidth = pageRect.width * 0.8
// 2
let aspectWidth = maxWidth / image.size.width
let aspectHeight = maxHeight / image.size.height
let aspectRatio = min(aspectWidth, aspectHeight)
// 3
let scaledWidth = image.size.width * aspectRatio
let scaledHeight = image.size.height * aspectRatio
// 4
let imageX = (pageRect.width - scaledWidth) / 2.0
let imageRect = CGRect(x: imageX, y: imageTop,
width: scaledWidth, height: scaledHeight)
// 5
image.draw(in: imageRect)
return imageRect.origin.y + imageRect.size.height
}
// 1
func drawTearOffs(_ drawContext: CGContext, pageRect: CGRect,
tearOffY: CGFloat, numberTabs: Int) {
// 2
drawContext.saveGState()
drawContext.setLineWidth(2.0)
// 3
drawContext.move(to: CGPoint(x: 0, y: tearOffY))
drawContext.addLine(to: CGPoint(x: pageRect.width, y: tearOffY))
drawContext.strokePath()
drawContext.restoreGState()
// 4
drawContext.saveGState()
let dashLength = CGFloat(72.0 * 0.2)
drawContext.setLineDash(phase: 0, lengths: [dashLength, dashLength])
// 5
let tabWidth = pageRect.width / CGFloat(numberTabs)
for tearOffIndex in 1..
后记
本篇主要讲述了基于PDFKit的PDF文档的创建和分享,感兴趣的给个赞或者关注~~~