创建多页PDF [英] Create PDF with multiple pages

查看:133
本文介绍了创建多页PDF的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要实现创建具有多个文本页面的pdf的功能.

I need to implement a functionality of creating pdf with multiple pages of a text.

class PDFCreator {

func prepareData() -> Data {
    //1
    let pdfMetaData = [
      kCGPDFContextCreator: "PDF Creator",
      kCGPDFContextAuthor: "Pratik Sodha",
      kCGPDFContextTitle: "My PDF"
    ]

    //2
    let format = UIGraphicsPDFRendererFormat()
    format.documentInfo = pdfMetaData as [String: Any]

    //3
    let pageWidth = 8.5 * 72.0
    let pageHeight = 11 * 72.0
    let pageRect = CGRect(x: 0, y: 0, width: pageWidth, height: pageHeight)

    //4
    let renderer = UIGraphicsPDFRenderer(bounds: pageRect, format: format)

    //5
    let data = renderer.pdfData { (context) in
        //6
        context.beginPage()
        self.addText("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.", pageRect: pageRect)

    }

    return data
}

@discardableResult
func addText(_ text : String, pageRect: CGRect) -> CGFloat {

    // 1
    let textFont = UIFont.systemFont(ofSize: 60.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: text, attributes: textAttributes)
    let textSize = attributedText.boundingRect(with: pageRect.size, options: [.usesFontLeading, .usesLineFragmentOrigin], context: nil)

    // 4
    let textRect = CGRect(x: 10,
                          y: 10,
                          width: pageRect.width - 20,
                          height: textSize.height)

    attributedText.draw(in: textRect)

    return textRect.origin.y + textRect.size.height
  }
}

使用PDFCreator类准备pdf数据并使用PDFView进行显示.

Using PDFCreator class prepare pdf data and display using PDFView.

import UIKit
import PDFKit

class PDFPreviewViewController: UIViewController {

    //1
    @IBOutlet weak private var pdfView : PDFView!

    override func viewDidLoad() {

        super.viewDidLoad()

        //2
        let pdfData = PDFCreator().prepareData()

        //3
        pdfView.document = PDFDocument(data: pdfData)
        pdfView.autoScales = true
    }
}

实际输出

例外输出

整个文本将在PDF中带有新的PDF页面,而不会减小字体大小.

Whole text will be in PDF with new PDF page without decreasing font size.

任何帮助,不胜感激. 谢谢你.

Any help much appreciated. Thank you.

推荐答案

输出

使用CTFramesetterCreateFrameCFAttributedStringGetLength


class PDFCreator {

lazy var pageWidth : CGFloat  = {
    return 8.5 * 72.0
}()

lazy var pageHeight : CGFloat = {
    return 11 * 72.0
}()

lazy var pageRect : CGRect = {
    CGRect(x: 0, y: 0, width: pageWidth, height: pageHeight)
}()

lazy var marginPoint : CGPoint = {
    return CGPoint(x: 10, y: 10)
}()

lazy var marginSize : CGSize = {
    return CGSize(width: self.marginPoint.x * 2 , height: self.marginPoint.y * 2)
}()


func prepareData() -> Data {
    //1
    let pdfMetaData = [
      kCGPDFContextCreator: "PDF Creator",
      kCGPDFContextAuthor: "Pratik Sodha",
      kCGPDFContextTitle: "My PDF"
    ]

    //2
    let format = UIGraphicsPDFRendererFormat()
    format.documentInfo = pdfMetaData as [String: Any]

    //3
    let renderer = UIGraphicsPDFRenderer(bounds: pageRect, format: format)

    //5
    let data = renderer.pdfData { (context) in

        //6
        self.addText("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.", context: context)
    }

    return data
}

@discardableResult
func addText(_ text : String, context : UIGraphicsPDFRendererContext) -> CGFloat {

    // 1
    let textFont = UIFont.systemFont(ofSize: 60.0, weight: .regular)

    // 2
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.alignment = .natural
    paragraphStyle.lineBreakMode = .byWordWrapping

    // 3
    let textAttributes = [
        NSAttributedString.Key.paragraphStyle: paragraphStyle,
        NSAttributedString.Key.font: textFont
    ]

    //4
    let currentText = CFAttributedStringCreate(nil,
                                               text as CFString,
                                               textAttributes as CFDictionary)
    //5
    let framesetter = CTFramesetterCreateWithAttributedString(currentText!)

    //6
    var currentRange = CFRangeMake(0, 0)
    var currentPage = 0
    var done = false
    repeat {

        //7
        /* Mark the beginning of a new page.*/
        context.beginPage()

        //8
        /*Draw a page number at the bottom of each page.*/
        currentPage += 1
        drawPageNumber(currentPage)


        //9
        /*Render the current page and update the current range to
          point to the beginning of the next page. */
        currentRange = renderPage(currentPage,
                                  withTextRange: currentRange,
                                  andFramesetter: framesetter)

        //10
        /* If we're at the end of the text, exit the loop. */
        if currentRange.location == CFAttributedStringGetLength(currentText) {
            done = true
        }

    } while !done

    return CGFloat(currentRange.location + currentRange.length)
}

func renderPage(_ pageNum: Int, withTextRange currentRange: CFRange, andFramesetter framesetter: CTFramesetter?) -> CFRange {
    var currentRange = currentRange
    // Get the graphics context.
    let currentContext = UIGraphicsGetCurrentContext()

    // Put the text matrix into a known state. This ensures
    // that no old scaling factors are left in place.
    currentContext?.textMatrix = .identity

    // Create a path object to enclose the text. Use 72 point
    // margins all around the text.
    let frameRect = CGRect(x: self.marginPoint.x, y: self.marginPoint.y, width: self.pageWidth - self.marginSize.width, height: self.pageHeight - self.marginSize.height)
    let framePath = CGMutablePath()
    framePath.addRect(frameRect, transform: .identity)

    // Get the frame that will do the rendering.
    // The currentRange variable specifies only the starting point. The framesetter
    // lays out as much text as will fit into the frame.
    let frameRef = CTFramesetterCreateFrame(framesetter!, currentRange, framePath, nil)

    // Core Text draws from the bottom-left corner up, so flip
    // the current transform prior to drawing.
    currentContext?.translateBy(x: 0, y: self.pageHeight)
    currentContext?.scaleBy(x: 1.0, y: -1.0)

    // Draw the frame.
    CTFrameDraw(frameRef, currentContext!)

    // Update the current range based on what was drawn.
    currentRange = CTFrameGetVisibleStringRange(frameRef)
    currentRange.location += currentRange.length
    currentRange.length = CFIndex(0)

    return currentRange
}

func drawPageNumber(_ pageNum: Int) {

    let theFont = UIFont.systemFont(ofSize: 20)

    let pageString = NSMutableAttributedString(string: "Page \(pageNum)")
    pageString.addAttribute(NSAttributedString.Key.font, value: theFont, range: NSRange(location: 0, length: pageString.length))

    let pageStringSize =  pageString.size()

    let stringRect = CGRect(x: (pageRect.width - pageStringSize.width) / 2.0,
                            y: pageRect.height - (pageStringSize.height) / 2.0 - 15,
                            width: pageStringSize.width,
                            height: pageStringSize.height)

    pageString.draw(in: stringRect)

}
}

使用PDFCreator类准备pdf数据并使用PDFView进行显示.

Using PDFCreator class prepare pdf data and display using PDFView.

import UIKit
import PDFKit

class PDFPreviewViewController: UIViewController {

    //1
    @IBOutlet weak private var pdfView : PDFView!

    override func viewDidLoad() {

        super.viewDidLoad()

        //2
        let pdfData = PDFCreator().prepareData()

        //3
        pdfView.document = PDFDocument(data: pdfData)
        pdfView.autoScales = true
    }
}

这篇关于创建多页PDF的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆