UIWebView到PDF的Objective-C问题 [英] Objective-C Issues with UIWebView to PDF

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

问题描述

我这里有这个方法,它将我的UIWebView转换成PDF并且运行良好。但是,当我打印此PDF或通过电子邮件发送它时,它会被切断。它就像它只生成我设置的UIWebView的大小(宽度:688& height:577)如果我增加UIWebView的大小,比如900或1024我的PDF是空的。我的UIWebView大于577,但在我的应用程序中,我可以滚动。

I have this method here that takes my UIWebView and convert into a PDF and its working well. But when I print off this PDF or email it, its cut off. Its like its only generating what the size of the UIWebView that I set (which is width: 688 & height: 577) If I increase the size of the UIWebView to lets say 900 or 1024 my PDF is empty. My UIWebView is bigger than 577, but in my app, I am able to scroll.

这是方法....

-(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];
}

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

I hope this makes sense....Does anyone have any suggestions on how to fix this, so the PDF is not cut off?

我忘记提及这些变量:

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

这是我的分享按钮:

- (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创建PDF的更通用的方式,到目前为止它一直很适合我。我用Xcode 6和iOS 8.2测试了这个解决方案。此外,尝试打印生成的PDF和打印出来的所有内容。

I've done this in the past using UIPrintPageRenderer. It's a more versetile way of creating a PDF from a UIWebView, and it's been working well for me so far. I've tested this solution with Xcode 6 and iOS 8.2. Also, tried printing the resulting PDF and everything printed out fine.

当我阅读OP时,我做了一些不同页面大小的测试,看看我是否能得到一个空白PDF。我发现了一些关键项,可能会导致空白的PDF文件。我已在代码中识别它们。

When I read the OP, I did some testing with various page sizes, to see if I can get a blank PDF. There are a few key items that I identified, that could contribute to a blank PDF file. I've identified them in the code.

当调用webViewDidFinishLoad()时,视图可能不会100%加载。必须进行检查,以查看视图是否仍在加载。这很重要,因为它可能是您问题的根源。如果不是,那么我们很高兴。这里有一个非常重要的注意事项。一些网页是动态加载的(在页面本身中定义)。以youtube.com为例。页面几乎立即显示,并带有加载屏幕。这将欺骗我们的Web视图,并且它的isLoading属性将设置为false,而网页仍然会动态加载内容。这是一个非常罕见的情况,在一般情况下,这个解决方案将运作良好。如果需要从这样的动态加载网页生成PDF文件,则可能需要将实际生成移动到其他位置。即使使用动态加载网页,您最终也会看到显示加载屏幕的PDF,而不是空PDF文件。

When webViewDidFinishLoad() gets called, the view might not be 100% loaded. A check is necessary, to see if the view is still loading. This is important, as it might be the source of your problem. If it's not, then we are good to go. There is a very important note here. Some web pages are loaded dynamically (defined in the page itself). Take youtube.com for example. The page displays almost immediately, with a "loading" screen. This will trick our web view, and it's "isLoading" property will be set to "false", while the web page is still loading content dynamically. This is a pretty rare case though, and in the general case this solution will work well. If you need to generate a PDF file from such a dynamic loading web page, you might need to move the actual generation to a different spot. Even with a dynamic loading web page, you will end up with a PDF showing the loading screen, and not an empty PDF file.

另一个关键方面是设置printableRect和pageRect。请注意,这些是单独设置的。如果printableRect小于paperRect,则最终会在内容周围添加一些填充 - 例如,请参阅代码。这是一个链接到Apple的API文档,并附有一些简短描述。

Another key aspect is setting the printableRect and pageRect. Note that those are set separately. If the printableRect is smaller than the paperRect, you will end up with some padding around the content - see code for example. Here is a link to Apple's API doc with some short descriptions for both.

下面的示例代码将一个类别添加到UIPrintPageRenderer以创建实际的PDF数据。此示例中的代码在过去使用各种在线资源汇总在一起,我无法找到哪些资源用于正确信用。

The example code below adds a Category to UIPrintPageRenderer to create the actual PDF data. The code in this sample has been put together using various resources online in the past, and I wasn't able to find which ones were used to credit them properly.

@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()中的内容

And here is what I have in 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页面大小。它可以编辑以满足您的需求。

PDFSize is defined as a constant, set to a standard A4 page size. It can be edited to meet your needs.

#define PDFSize CGSizeMake(595.2,841.8)

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

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