2015-05-12 2 views
6

У меня есть этот метод, который использует мой UIWebView и конвертирует в PDF-файл и хорошо работает. Но когда я распечатываю этот PDF-файл или отправляю его по электронной почте, он отключается. Это похоже на то, что размер UIWebView, который я установил (ширина: 688 & height: 577) Если я увеличу размер UIWebView до 300 или 1024, мой PDF-файл пуст. Мой UIWebView больше 577, но в моем приложении я могу прокручивать.Задачи-C Проблемы с UIWebView в PDF

Вот способ ....

-(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 не отрезан?

Я забыл упомянуть эти переменные:

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

} 
+0

Так что же это связано с Objective-C? – matt

+0

этот метод Objective-C – user979331

+0

Очевидно, что ваш код находится в Objective-C. Любой может это видеть. Но вопрос не о _ Objective-C. Независимо от того, какой ответ будет одинаковым, используете ли вы Objective-C, Swift, AppleScript или что-то еще. – matt

ответ

5

Я делал это в прошлом, используя UIPrintPageRenderer. Это более реалистичный способ создания PDF-файла из UIWebView, и он работает для меня до сих пор. Я протестировал это решение с помощью Xcode 6 и iOS 8.2. Кроме того, попробовал распечатать полученный PDF-файл и все распечатывалось в порядке.

Когда я прочитал OP, я провел некоторое тестирование с различными размерами страниц, чтобы узнать, могу ли я получить пустой PDF-файл. Есть несколько ключевых элементов, которые я определил, которые могут внести вклад в пустой PDF-файл. Я определил их в коде.

Когда вызывается вызов webViewDidFinishLoad(), представление может быть не загружено на 100%. Необходима проверка, чтобы увидеть, продолжает ли просмотр. Это важно, поскольку это может быть источником вашей проблемы. Если это не так, тогда нам хорошо идти. Здесь очень важно отметить. Некоторые веб-страницы загружаются динамически (определенные на самой странице). Возьмите, к примеру, youtube.com. Страница отображается почти сразу, с экраном загрузки. Это обманет наш веб-просмотр, и его свойство isLoading будет установлено на «false», в то время как веб-страница по-прежнему загружает контент динамически. Однако это довольно редкий случай, и в общем случае это решение будет работать хорошо. Если вам нужно создать PDF-файл с такой страницы динамической загрузки, вам может потребоваться переместить фактическое поколение в другое место. Даже с веб-страницей динамической загрузки вы получите PDF-файл, показывающий экран загрузки, а не пустой файл PDF.

Другим ключевым аспектом является настройка printableRect и pageRect. Обратите внимание, что они устанавливаются отдельно. Если значение printableRect меньше, чем paperRect, вы получите некоторое дополнение к содержимому - см., Например, код. Вот link в API API от Apple с некоторыми краткими описаниями для обоих.

Приведенный ниже примерный пример добавляет категорию в UIPrintPageRenderer для создания фактических данных PDF. Код в этом примере был составлен с использованием различных ресурсов в Интернете в прошлом, и я не смог найти, какие из них были использованы для их надлежащего кредитования.

@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) 
+0

Я получаю сообщение об ошибке с этим кодом: PDFSize не определен. что это должно быть. Кроме того, когда я нажимаю кнопку моего доступа, у меня есть, приложение выдает «попытку вставить нулевой объект из объектов» [0] 'Я обновил свой вопрос с помощью кнопки общего доступа – user979331

+0

PDFSize является константой. Он в основном определяет размер вашей страницы. Я бы использовал здесь что-то стандартное, и поэтому у меня он установлен на A4. Вы можете изменить его, чтобы получить необходимый размер страницы. –

+0

Что касается действия share(), вы столкнетесь с проблемой, когда PDF недоступен по указанному вами пути. Есть несколько вещей, которые вы можете попробовать - убедитесь, что вы используете один и тот же путь для сохранения и для совместного использования файла. Другое дело, и это важно, убедитесь, что файл PDF фактически создан и доступен в этом пути. Я тестировал действие на моем конце, и я не получаю краху. –

2

Для того чтобы создать файл PDF в памяти, вы должны сделать слой экземпляра UIWebBrowserView, который лежит под UIWebView «s scrollView. Для того, чтобы сделать это, попробуйте изменить ваш renderInContext: вызов следующим образом:

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

Кроме того, если цель IOS> = 7.0, то вы можете избежать использования renderInContext: и использовать один из snapshotViewAfterScreenUpdates: или drawViewHierarchyInRect:afterScreenUpdates: методов.

+0

где бы я поместил это в свой метод? – user979331

+0

Замените вызов, который у вас уже есть: '[webViewPDF.layer renderInContext: currentContext];' – Dalzhim

+0

Ты мой Бог! Спасибо! – rusBogun

Смежные вопросы