有很多关于如何在应用UIView
中显示PDF的资源。我现在正在做的是从UIViews
创建一个PDF。
例如,我有UIView
个子视图,例如文字视图,UILabels
,UIImages
,那么如何转换大 {{1}整体上包括它的所有子视图和子视图到PDF?
我查了Apple's iOS reference。但是,它只涉及将文本/图像片段写入PDF文件。
我面临的问题是我想以PDF格式写入文件的内容很多。如果我将它们逐个写入PDF,那将是一项巨大的工作。
这就是为什么我正在寻找一种方法将UIView
写入PDF甚至位图。
我已经尝试过在Stack Overflow中从其他Q / A复制的源代码。但它只给了我一个UIViews
边界大小的空白PDF。
UIView
请帮忙。感谢。
答案 0 :(得分:119)
请注意,以下方法会创建视图的只是位图;它不会创建实际的排版。
(void)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename
{
// Creates a mutable data object for updating with binary data, like a byte array
NSMutableData *pdfData = [NSMutableData data];
// Points the pdf converter to the mutable data object and to the UIView to be converted
UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil);
UIGraphicsBeginPDFPage();
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
// draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData
[aView.layer renderInContext:pdfContext];
// remove PDF rendering context
UIGraphicsEndPDFContext();
// Retrieves the document directories from the iOS device
NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString* documentDirectory = [documentDirectories objectAtIndex:0];
NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename];
// instructs the mutable data object to write its context to a file on disk
[pdfData writeToFile:documentDirectoryFilename atomically:YES];
NSLog(@"documentDirectoryFileName: %@",documentDirectoryFilename);
}
还要确保导入: QuartzCore / QuartzCore.h
答案 1 :(得分:22)
此外,如果有人有兴趣,这里是Swift 3代码:
func createPdfFromView(aView: UIView, saveToDocumentsWithFileName fileName: String)
{
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil)
UIGraphicsBeginPDFPage()
guard let pdfContext = UIGraphicsGetCurrentContext() else { return }
aView.layer.render(in: pdfContext)
UIGraphicsEndPDFContext()
if let documentDirectories = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first {
let documentsFileName = documentDirectories + "/" + fileName
debugPrint(documentsFileName)
pdfData.write(toFile: documentsFileName, atomically: true)
}
}
答案 2 :(得分:10)
如果有人有兴趣,这里是Swift 2.1代码:
func createPdfFromView(aView: UIView, saveToDocumentsWithFileName fileName: String)
{
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil)
UIGraphicsBeginPDFPage()
guard let pdfContext = UIGraphicsGetCurrentContext() else { return }
aView.layer.renderInContext(pdfContext)
UIGraphicsEndPDFContext()
if let documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first {
let documentsFileName = documentDirectories + "/" + fileName
debugPrint(documentsFileName)
pdfData.writeToFile(documentsFileName, atomically: true)
}
}
答案 3 :(得分:3)
从UIView创建PDF的超级简单方法是使用UIView Extension
Swift 4.2
extension UIView {
// Export pdf from Save pdf in drectory and return pdf file path
func exportAsPdfFromView() -> String {
let pdfPageFrame = self.bounds
let pdfData = NSMutableData()
UIGraphicsBeginPDFContextToData(pdfData, pdfPageFrame, nil)
UIGraphicsBeginPDFPageWithInfo(pdfPageFrame, nil)
guard let pdfContext = UIGraphicsGetCurrentContext() else { return "" }
self.layer.render(in: pdfContext)
UIGraphicsEndPDFContext()
return self.saveViewPdf(data: pdfData)
}
// Save pdf file in document directory
func saveViewPdf(data: NSMutableData) -> String {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let docDirectoryPath = paths[0]
let pdfPath = docDirectoryPath.appendingPathComponent("viewPdf.pdf")
if data.write(to: pdfPath, atomically: true) {
return pdfPath.path
} else {
return ""
}
}
}
信用:http://www.swiftdevcenter.com/create-pdf-from-uiview-wkwebview-and-uitableview/
答案 4 :(得分:2)
这将从UIView生成PDF并打开打印对话框,目标C.
将- (IBAction)PrintPDF:(id)sender
附加到屏幕上的按钮。
添加#import <QuartzCore/QuartzCore.h>
框架
H档
@interface YourViewController : UIViewController <MFMailComposeViewControllerDelegate,UIPrintInteractionControllerDelegate>
{
UIPrintInteractionController *printController;
}
- (IBAction)PrintPDF:(id)sender;
M档
-(void)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename
{
NSMutableData *pdfData = [NSMutableData data];
UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil);
UIGraphicsBeginPDFPage();
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
[aView.layer renderInContext:pdfContext];
UIGraphicsEndPDFContext();
NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString* documentDirectory = [documentDirectories objectAtIndex:0];
NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename];
NSString *file = [documentDirectory stringByAppendingPathComponent:@"yourPDF.pdf"];
NSURL *urlPdf = [NSURL fileURLWithPath: file];
[pdfData writeToFile:documentDirectoryFilename atomically:YES];
NSLog(@"documentDirectoryFileName: %@",documentDirectoryFilename);
}
- (IBAction)PrintPDF:(id)sender
{
[self createPDFfromUIView:self.view saveToDocumentsWithFileName:@"yourPDF.pdf"];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"yourPDF.pdf"];
NSData *myData = [NSData dataWithContentsOfFile: path];
UIPrintInteractionController *pic = [UIPrintInteractionController sharedPrintController];
if(pic && [UIPrintInteractionController canPrintData: myData] ) {
pic.delegate = self;
UIPrintInfo *printInfo = [UIPrintInfo printInfo];
printInfo.outputType = UIPrintInfoOutputGeneral;
printInfo.jobName = [path lastPathComponent];
printInfo.duplex = UIPrintInfoDuplexLongEdge;
pic.printInfo = printInfo;
pic.showsPageRange = YES;
pic.printingItem = myData;
void (^completionHandler)(UIPrintInteractionController *, BOOL, NSError *) = ^(UIPrintInteractionController *pic, BOOL completed, NSError *error) {
//self.content = nil;
if(!completed && error){
NSLog(@"Print Error: %@", error);
}
};
[pic presentAnimated:YES completionHandler:completionHandler];
}
}
答案 5 :(得分:2)
使用Swift 4.2,您可以将CALayer
的{{3}}方法与UIGraphicsPDFRenderer
的{{3}}方法结合起来,以便从{{1} }实例。
以下Playground示例代码显示了如何使用UIView
和render(in:)
:
writePDF(to:withActions:)
注意:为了在您的Playground中使用render(in:)
,首先需要在macOS的“ Documents”文件夹中创建一个名为“ Shared Playground Data”的文件夹。
下面的import UIKit
import PlaygroundSupport
let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
view.backgroundColor = .orange
let subView = UIView(frame: CGRect(x: 20, y: 20, width: 40, height: 60))
subView.backgroundColor = .magenta
view.addSubview(subView)
let outputFileURL = PlaygroundSupport.playgroundSharedDataDirectory.appendingPathComponent("MyPDF.pdf")
let pdfRenderer = UIGraphicsPDFRenderer(bounds: view.bounds)
do {
try pdfRenderer.writePDF(to: outputFileURL, withActions: { context in
context.beginPage()
view.layer.render(in: context.cgContext)
})
} catch {
print("Could not create PDF file: \(error)")
}
子类完整实现显示了一种重构iOS应用程序前面示例的可能方法:
UIViewController
答案 6 :(得分:-4)
我不知道为什么,但是casilic的回答让我在iOS 6.1上出现了空白屏幕。以下代码有效。
-(NSMutableData *)createPDFDatafromUIView:(UIView*)aView
{
// Creates a mutable data object for updating with binary data, like a byte array
NSMutableData *pdfData = [NSMutableData data];
// Points the pdf converter to the mutable data object and to the UIView to be converted
UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil);
UIGraphicsBeginPDFPage();
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
// draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData
[aView.layer renderInContext:pdfContext];
// remove PDF rendering context
UIGraphicsEndPDFContext();
return pdfData;
}
-(NSString*)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename
{
// Creates a mutable data object for updating with binary data, like a byte array
NSMutableData *pdfData = [self createPDFDatafromUIView:aView];
// Retrieves the document directories from the iOS device
NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString* documentDirectory = [documentDirectories objectAtIndex:0];
NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename];
// instructs the mutable data object to write its context to a file on disk
[pdfData writeToFile:documentDirectoryFilename atomically:YES];
NSLog(@"documentDirectoryFileName: %@",documentDirectoryFilename);
return documentDirectoryFilename;
}