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

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

问题描述

我这里有这个方法,它可以将我的 UIWebView 转换为 PDF 并且效果很好.但是当我打印出这个 PDF 或通过电子邮件发送它时,它被切断了.它就像它只生成我设置的 UIWebView 的大小(宽度:688 和高度: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天全站免登陆