我有一段很长NSAttributedString
,我试图绘制为PDF,使用绘图功能制作单页PDF非常简单:
func createPDFFilea(atext: NSAttributedString) -> NSMutableData {
let pdfData = NSMutableData()
let paperRect = CGRect(x: 0, y: 0, width: 595.2, height: 841.8);
UIGraphicsBeginPDFContextToData(pdfData, paperRect, nil)
UIGraphicsBeginPDFPage()
atext.draw(in: paperRect)
UIGraphicsEndPDFContext()
return pdfData
}
但如果文字超过paperRect
则会丢失,如何管理?
PS。这里有一个类似的解决方案,对于obj-C只有一个简单的NSString
http://www.coderzheaven.com/2016/09/07/create-pdf-in-ios/
但我无法弄清楚在Swift中得到它,似乎官方的苹果文档也只适用于obj-C
https://developer.apple.com/library/content/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GeneratingPDF/GeneratingPDF.html
答案 0 :(得分:1)
我终于设法将obj-C代码转换为swift3
func createPDFwithAttributedString(_ currentText: NSAttributedString) -> NSMutableData {
let pdfData = NSMutableData()
// Create the PDF context using the default page size of 612 x 792.
UIGraphicsBeginPDFContextToData(pdfData, CGRect.zero, nil)
let framesetter = CTFramesetterCreateWithAttributedString(currentText)
var currentRange = CFRangeMake(0, 0);
var currentPage = 0;
var done = false;
repeat {
// Mark the beginning of a new page.
UIGraphicsBeginPDFPageWithInfo(CGRect(x: 0, y: 0, width: 612, height: 792), nil);
// Draw a page number at the bottom of each page.
currentPage += 1;
// Render the current page and update the current range to
// point to the beginning of the next page.
renderPagewithTextRange(currentRange: ¤tRange, framesetter: framesetter)
// If we're at the end of the text, exit the loop.
if (currentRange.location == CFAttributedStringGetLength(currentText)){
done = true;
}
} while (!done);
// Close the PDF context and write the contents out.
UIGraphicsEndPDFContext();
return pdfData
}
func renderPagewithTextRange (currentRange: inout CFRange, framesetter: CTFramesetter) {
// Get the graphics context.
if let currentContext = UIGraphicsGetCurrentContext(){
// Put the text matrix into a known state. This ensures
// that no old scaling factors are left in place.
currentContext.textMatrix = CGAffineTransform.identity;
// Create a path object to enclose the text. Use 72 point
// margins all around the text.
let frameRect = CGRect(x: 72, y: 72, width: 468, height: 648);
let framePath = CGMutablePath();
framePath.addRect(frameRect)
// 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: 792);
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 = 0;
}
}