2015-05-12 17 views
6

Tôi có phương pháp này ở đây có UIWebView của tôi và chuyển đổi thành PDF và hoạt động tốt. Nhưng khi tôi in ra PDF này hoặc gửi email, nó bị cắt. Nó giống như nó chỉ tạo ra kích thước của UIWebView mà tôi đặt (chiều rộng: 688 & chiều cao: 577) Nếu tôi tăng kích thước của UIWebView để cho phép nói 900 hoặc 1024 tệp PDF của tôi trống. UIWebView của tôi lớn hơn 577, nhưng trong ứng dụng của tôi, tôi có thể cuộn.Các vấn đề mục tiêu-C với UIWebView sang PDF

Đây là phương pháp ....

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

Tôi hy vọng điều này có ý nghĩa .... Có ai có bất kỳ gợi ý về cách để sửa lỗi này, vì vậy PDF được không cắt đứt?

tôi quên đề cập đến các biến:

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

Đây là nút chia sẻ của tôi:

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

} 
+0

Vậy điều này có liên quan gì đến Objective-C? – matt

+0

phương pháp này là Mục tiêu-C – user979331

+0

Rõ ràng mã của bạn sẽ xảy ra trong mục tiêu-C. Bất cứ ai cũng có thể thấy điều đó. Nhưng câu hỏi không phải là _about_ Objective-C. Dù câu trả lời là như thế nào cho dù bạn đang sử dụng Objective-C, Swift, AppleScript hay bất kỳ thứ gì. – matt

Trả lời

5

Tôi đã làm điều này trong quá khứ sử dụng UIPrintPageRenderer. Đó là một cách dễ hiểu hơn khi tạo PDF từ UIWebView và nó đã hoạt động tốt cho tôi cho đến nay. Tôi đã thử nghiệm giải pháp này với Xcode 6 và iOS 8.2. Ngoài ra, đã thử in PDF kết quả và mọi thứ được in ra tốt.

Khi tôi đọc OP, tôi đã thực hiện một số thử nghiệm với các kích thước trang khác nhau, để xem tôi có thể nhận được một tệp PDF trống hay không. Có một vài mục chính mà tôi đã xác định, có thể đóng góp vào tệp PDF trống. Tôi đã xác định chúng trong mã.

Khi webViewDidFinishLoad() được gọi, chế độ xem có thể không được tải 100%. Cần kiểm tra để xem liệu chế độ xem có đang tải hay không. Điều này là quan trọng, vì nó có thể là nguồn gốc của vấn đề của bạn. Nếu không, thì chúng ta nên đi. Có một lưu ý rất quan trọng ở đây. Một số trang web được tải động (được xác định trong chính trang đó). Lấy youtube.com làm ví dụ. Trang hiển thị gần như ngay lập tức, với màn hình "tải". Điều này sẽ đánh lừa chế độ xem web của chúng tôi và thuộc tính "isLoading" sẽ được đặt thành "sai", trong khi trang web vẫn đang tải nội dung động. Đây là một trường hợp khá hiếm, và trong trường hợp chung giải pháp này sẽ hoạt động tốt. Nếu bạn cần tạo một tệp PDF từ một trang web tải động như vậy, bạn có thể cần di chuyển thế hệ thực tế đến một vị trí khác. Ngay cả với trang web tải động, bạn sẽ kết thúc bằng một tệp PDF hiển thị màn hình tải chứ không phải tệp PDF trống.

Một khía cạnh quan trọng khác là đặt printableRect và pageRect. Lưu ý rằng chúng được đặt riêng. Nếu printableRect nhỏ hơn paperRect, bạn sẽ kết thúc với một số phần đệm xung quanh nội dung - xem mã ví dụ. Dưới đây là link đến tài liệu API của Apple với một số mô tả ngắn cho cả hai.

Mã ví dụ bên dưới thêm Danh mục vào UIPrintPageRenderer để tạo dữ liệu PDF thực. Mã trong mẫu này đã được đặt cùng nhau bằng cách sử dụng các tài nguyên trực tuyến khác nhau trong quá khứ và tôi không thể tìm thấy mã nào được sử dụng để ghi nhận chúng đúng cách.

@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 

Và đây là những gì tôi có trong 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 được định nghĩa như một hằng số, thiết lập để một kích thước trang A4 chuẩn. Nó có thể được chỉnh sửa để đáp ứng nhu cầu của bạn.

#define PDFSize CGSizeMake(595.2,841.8) 
+0

Tôi gặp lỗi với mã này: PDFSize không được xác định. nó nên là gì. Ngoài ra khi tôi nhấn nút chia sẻ của tôi, ứng dụng gặp sự cố 'cố chèn đối tượng nil từ đối tượng [0]' Tôi đã cập nhật câu hỏi của mình bằng nút chia sẻ – user979331

+0

PDFSize là một hằng số. Về cơ bản nó xác định kích thước trang của bạn. Tôi sẽ sử dụng một cái gì đó tiêu chuẩn ở đây, và đó là lý do tại sao tôi đã thiết lập nó thành A4. Bạn có thể sửa đổi nó để có được kích thước trang bạn cần. –

+0

Theo như hành động chia sẻ() của bạn, bạn sẽ gặp sự cố khi tệp PDF không khả dụng ở đường dẫn bạn đã xác định. Có một vài điều bạn có thể thử - đảm bảo bạn sử dụng cùng một đường dẫn để lưu và chia sẻ tệp. Điều khác, và điều này quan trọng hơn, hãy đảm bảo tệp PDF thực sự được tạo và có sẵn trong đường dẫn đó. Tôi đã thử nghiệm hành động trên đầu của tôi, và tôi không nhận được sự cố. –

2

Để tạo tập tin PDF của bạn trong bộ nhớ, bạn cần phải rút ra những lớp của UIWebBrowserView dụ nằm bên dưới phần 's scrollViewUIWebView. Để làm điều đó, hãy thử thay đổi renderInContext: cuộc gọi của bạn theo cách sau:

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

Ngoài ra, nếu bạn nhắm mục tiêu iOS> = 7.0, sau đó bạn có thể tránh sử dụng renderInContext: và sử dụng một trong những snapshotViewAfterScreenUpdates: hoặc drawViewHierarchyInRect:afterScreenUpdates: phương pháp.

+0

Tôi sẽ đặt phương thức này vào phương pháp của mình ở đâu? – user979331

+0

Thay thế cuộc gọi bạn đã có: '[webViewPDF.layer renderInContext: currentContext];' – Dalzhim

+0

Bạn là Chúa của tôi! Cảm ơn bạn! – rusBogun

Các vấn đề liên quan