在iOS中从UIWebView/UIView生成PDF的最佳方法

san*_*osh 5 pdf iphone objective-c uiwebview ios

在我的iOS应用程序中,我想从UIWebView/UIView(包括子视图)创建PDF.在我的应用程序中,我将首先在UIWebView中加载原始传入的PDF,然后在UIWebView上添加图像作为子视图.我想从UIWebview创建一个带有此图像(子视图)的PDF,原始清晰度并且没有数据丢失.

PS:渲染PDF中的图像应与UIWebView中的图像位于同一位置.

我可以从UIWebView创建PDF,但它缺乏PDF清晰度并产生边框问题.

任何人都可以从UIWebView(包括子视图)提供清晰的PDF渲染解决方案吗?

编辑内容:

在此输入图像描述

以上是UIWebView的屏幕截图.签名(测试)是子视图中的图像.我希望将其呈现为PDF,清晰且没有任何数据丢失.

在下面的答案中,UIPrintPageRenderer从UIWebView呈现PDF,但它忽略了UIWebView上方的子视图.这是此选项的主要问题.

使用createPDFfromUIView方法的另一个答案缺乏原始的清晰度:

   -(void)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename;
Run Code Online (Sandbox Code Playgroud)

此方法也会出现边框问题.

我还尝试使用参考中的以下代码直接在PDF上编写,无需截取屏幕截图.

- (void) drawCustomPDFContent
{
    //  Put your drawing calls here
    //  Draw a red box
    [[UIColor redColor] set];
    UIRectFill(CGRectMake(20, 20, 100, 100));

    //  Example of drawing your view into PDF, note that this will be a rasterized bitmap, including the text.
    //  To get smoother text you'll need to use the NSString draw methods
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    [view.layer renderInContext:ctx];
}

- (void) createCustomPDF
{
    NSURL* pdfURL = ... /* URL to pdf file */;
    CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((CFURLRef)pdfURL);

    const size_t numberOfPages = CGPDFDocumentGetNumberOfPages(pdf);

    NSMutableData* data = [NSMutableData data];
    UIGraphicsBeginPDFContextToData(data, CGRectZero, nil);

    for(size_t page = 1; page <= numberOfPages; page++)
    {
        //  Get the current page and page frame
        CGPDFPageRef pdfPage = CGPDFDocumentGetPage(pdf, page);
        const CGRect pageFrame = CGPDFPageGetBoxRect(pdfPage, kCGPDFMediaBox);

        UIGraphicsBeginPDFPageWithInfo(pageFrame, nil);

        //  Draw the page (flipped)
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        CGContextSaveGState(ctx);
        CGContextScaleCTM(ctx, 1, -1);
        CGContextTranslateCTM(ctx, 0, -pageFrame.size.height);
        CGContextDrawPDFPage(ctx, pdfPage);
        CGContextRestoreGState(ctx);

        if(page == 1)
        {
            [self drawCustomPDFContent];
        }
    }

    UIGraphicsEndPDFContext();

    CGPDFDocumentRelease(pdf);
    pdf = nil;

    //  Do something with data here
    [data writeToFile:... atomically:YES];
}
Run Code Online (Sandbox Code Playgroud)

它完成了这项工作.但是,UIWebView中的(x,y)坐标与原始PDF坐标不同,因此我无法映射要在PDF上绘制的精确坐标进行渲染.

希望这能解决我的问题.请建议一种方法来解决我的问题.如果可能不可能,请建议符合我要求的iOS PDF工具包/ SDK.

小智 0

-(void)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename
{
// Creates a mutable data object for updating with binary data, like a byte array
UIWebView *webView = (UIWebView*)aView;
NSString *heightStr = [webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight;"];

int height = [heightStr intValue];
//  CGRect screenRect = [[UIScreen mainScreen] bounds];
//  CGFloat screenHeight = (self.contentWebView.hidden)?screenRect.size.width:screenRect.size.height;
CGFloat screenHeight = webView.bounds.size.height;
int pages = ceil(height / screenHeight);

NSMutableData *pdfData = [NSMutableData data];
UIGraphicsBeginPDFContextToData(pdfData, webView.bounds, nil);
CGRect frame = [webView frame];
for (int i = 0; i < pages; i++) {
  // Check to screenHeight if page draws more than the height of the UIWebView
    if ((i+1) * screenHeight  > height) {
        CGRect f = [webView frame];
        f.size.height -= (((i+1) * screenHeight) - height);
        [webView setFrame: f];
    }

    UIGraphicsBeginPDFPage();
    CGContextRef currentContext = UIGraphicsGetCurrentContext();
//  CGContextTranslateCTM(currentContext, 72, 72); // Translate for 1" margins

    [[[webView subviews] lastObject] setContentOffset:CGPointMake(0, screenHeight * i) animated:NO];
    [webView.layer renderInContext:currentContext];
}

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];
[webView setFrame:frame];
 }
Run Code Online (Sandbox Code Playgroud)