Objective-C与UIWebView到PDF的问题

我在这里有这个方法,需要我的UIWebView和转换成PDF和它的工作。 但是,当我打印这个PDF或电子邮件,它的中断。 它像它唯一的生成什么大小的UIWebView,我设置(这是宽度:688&高度:577)如果我增加UIWebView的大小可以说900或1024我的PDF是空的。 我的UIWebView大于577,但在我的应用程序,我可以滚动。

这里是方法….

-(void)webViewDidFinishLoad:(UIWebView *)webViewPDF { CGRect origframe = webViewPDF.frame; NSString *heightStr = [webViewPDF stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight;"]; // Get the height of our webView int height = [heightStr intValue]; CGFloat maxHeight = kDefaultPageHeight - 2*kMargin; int pages = floor(height / maxHeight); NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *path = [paths objectAtIndex:0]; self.pdfPath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"Purchase Order.pdf"]]; UIGraphicsBeginPDFContextToFile(self.pdfPath, CGRectZero, nil); for (int i = 0; i < pages; i++) { if (maxHeight * (i+1) > height) { CGRect f = [webViewPDF frame]; f.size.height -= (((i+1) * maxHeight) - height); [webViewPDF setFrame: f]; } UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, kDefaultPageWidth, kDefaultPageHeight), nil); CGContextRef currentContext = UIGraphicsGetCurrentContext(); CGContextTranslateCTM(currentContext, kMargin, kMargin); [webViewPDF.layer renderInContext:currentContext]; } UIGraphicsEndPDFContext(); [webViewPDF setFrame:origframe]; [[[webViewPDF subviews] lastObject] setContentOffset:CGPointMake(0, 0) animated:NO]; } 

我希望这是有道理的….有没有人有任何build议如何解决这个问题,所以PDF不被切断?

我忘了提及这些变数:

 #define kDefaultPageHeight 850 #define kDefaultPageWidth 850 #define kMargin 50 

这是我的分享button:

 - (IBAction)Share:(id)sender { NSData *pdfData = [NSData dataWithContentsOfFile:self.pdfPath]; UIActivityViewController * activityController = [[UIActivityViewController alloc] initWithActivityItems:@[pdfData] applicationActivities:nil]; UIPopoverController *popup = [[UIPopoverController alloc] initWithContentViewController:activityController]; [popup presentPopoverFromRect:CGRectMake(self.view.frame.size.width - 36, 60, 0, 0)inView:self.view permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES]; } 

我在过去使用UIPrintPageRenderer完成了这项工作。 这是从UIWebView创build一个PDF更加丰富多彩的方式,到目前为止我一直在为我工作。 我用Xcode 6和iOS 8.2testing了这个解决scheme。 此外,试图打印生成的PDF和一切打印出来罚款。

当我阅读OP时,我用不同的页面大小做了一些testing,看能不能得到一个空白的PDF。 有几个我确定的关键项目,可能有助于一个空白的PDF文件。 我已经在代码中确定了它们。

当webViewDidFinishLoad()被调用时,视图可能不会100%加载。 检查是必要的,看看是否仍然加载视图。 这很重要,因为这可能是问题的根源。 如果不是,那么我们很好走。 这里有一个非常重要的说明。 一些网页是dynamic加载的(在页面中定义的)。 以youtube.com为例。 页面几乎立即显示,并带有“加载”屏幕。 这将欺骗我们的networking视图,并且它的“isLoading”属性将被设置为“false”,而网页仍在dynamic加载内容。 这是一个非常罕见的情况,在一般情况下,这个解决scheme将工作得很好。 如果您需要从这样的dynamic加载网页生成PDF文件,则可能需要将实际生成的代码移到其他位置。 即使使用dynamic加载网页,您最终的PDF也会显示加载屏幕,而不是空白的PDF文件。

另一个关键方面是设置printableRect和pageRect。 请注意,这些是分开设置的。 如果printableRect小于paperRect,则最终会在内容周围填充一些内容 – 例如,请参阅代码。 这里是一个链接到苹果的API文档和一些简短的说明。

下面的示例代码将一个类别添加到UIPrintPageRenderer以创build实际的PDF数据。 这个样本中的代码在过去已经在线使用了各种资源,我无法find哪些代码被正确地使用。

 @interface UIPrintPageRenderer (PDF) - (NSData*) createPDF; @end @implementation UIPrintPageRenderer (PDF) - (NSData*) createPDF { NSMutableData *pdfData = [NSMutableData data]; UIGraphicsBeginPDFContextToData( pdfData, self.paperRect, nil ); [self prepareForDrawingPages: NSMakeRange(0, self.numberOfPages)]; CGRect bounds = UIGraphicsGetPDFContextBounds(); for ( int i = 0 ; i < self.numberOfPages ; i++ ) { UIGraphicsBeginPDFPage(); [self drawPageAtIndex: i inRect: bounds]; } UIGraphicsEndPDFContext(); return pdfData; } @end 

这里是我在webViewDidFinishLoad()

 - (void)webViewDidFinishLoad:(UIWebView *)webViewIn { NSLog(@"web view did finish loading"); // webViewDidFinishLoad() could get called multiple times before // the page is 100% loaded. That's why we check if the page is still loading if (webViewIn.isLoading) return; UIPrintPageRenderer *render = [[UIPrintPageRenderer alloc] init]; [render addPrintFormatter:webViewIn.viewPrintFormatter startingAtPageAtIndex:0]; // Padding is desirable, but optional float padding = 10.0f; // Define the printableRect and paperRect // If the printableRect defines the printable area of the page CGRect paperRect = CGRectMake(0, 0, PDFSize.width, PDFSize.height); CGRect printableRect = CGRectMake(padding, padding, PDFSize.width-(padding * 2), PDFSize.height-(padding * 2)); [render setValue:[NSValue valueWithCGRect:paperRect] forKey:@"paperRect"]; [render setValue:[NSValue valueWithCGRect:printableRect] forKey:@"printableRect"]; // Call the printToPDF helper method that will do the actual PDF creation using values set above NSData *pdfData = [render createPDF]; // Save the PDF to a file, if creating one is successful if (pdfData) { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *path = [paths objectAtIndex:0]; NSString *pdfPath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"Purchase Order.pdf"]]; [pdfData writeToFile:pdfPath atomically:YES]; } else { NSLog(@"error creating PDF"); } } 

PDFSize被定义为一个常量,设置为一个标准的A4页面大小。 它可以编辑,以满足您的需求。

 #define PDFSize CGSizeMake(595.2,841.8) 

为了在内存中创buildPDF文件,需要绘制位于UIWebViewscrollView下面的UIWebBrowserView实例的scrollView 。 为了做到这一点,请尝试更改您的renderInContext:调用以下方法:

 UIView* contentView = webViewPDF.scrollView.subviews.firstObject; [contentView.layer renderInContext:currentContext]; 

此外,如果您的目标iOS> = 7.0,则可以避免使用renderInContext:并使用snapshotViewAfterScreenUpdates:drawViewHierarchyInRect:afterScreenUpdates:方法之一。