PDF内存警告/崩溃

时间:2013-05-03 10:50:16

标签: ios objective-c cocoa-touch memory-management pdf-generation

尽管在谷歌和So和http://developer.apple.com/library/ios/#documentation/2ddrawing/conceptual/drawingprintingios/GeneratingPDF/GeneratingPDF.html上进行了研究。我仍然无法通过我的应用找到这个问题的答案。加载视图后,我的应用会生成绘制到Web视图中的PDF。问题是,在收到内存警告和崩溃之前,我只能在iPhone 4上生成大约8页,在iPhone 5上生成14页。

ICPDFEICRInspection1 2,3,4等是在Web视图中绘制的大视图/ xib

目前,该应用会生成所有页面,然后在webView中显示整个文档。

我的问题:我如何更改此内容,因此我只能在用户滚动时一次绘制一页,而不是首先将其全部加载到内存中,循环显示内容将其绘制到一页一段时间

 - (void)viewWillAppear:(BOOL)animated
{
LogCmd();

 [super viewWillAppear:animated];
 if (self.pdfData != nil && self.viewHasUnloaded == YES) {
    self.viewHasUnloaded = NO;
    [self.webView loadData:self.pdfData MIMEType:@"application/pdf" textEncodingName:@"utf-8" baseURL:nil];
    }
   }



- (void)viewDidAppear:(BOOL)animated
  {

  LogCmd();
  [super viewDidAppear:animated];
  if (self.pdfData == nil) {



    // Generate PDF
     [ICUtils showProgressViewWithTitle:@"Generating PDF. This may take a minute..."];
     [self performSelectorInBackground:@selector(generatePdf) withObject:nil];
  }
 }

  - (void)generatePdf
   {
   NSMutableArray *pagesArray = [NSMutableArray array];

  if ([self.certificate.certificateType.title isEqualToString:@"EICR"]) {
    [pagesArray addObject:[[ICPDFEICRPage1 alloc] initWithCertificate:self.certificate]];
    [pagesArray addObject:[[ICPDFEICRPage2 alloc] initWithCertificate:self.certificate]];
    [self addObservationsToPagesArray:pagesArray];
    [self addDistributionBoardsToPagesArray:pagesArray];
    [pagesArray addObject:[[ICPDFEICRInspection alloc] initWithCertificate:self.certificate]];
    [pagesArray addObject:[[ICPDFEICRInspectionPage1 alloc] initWithCertificate:self.certificate]];
    [pagesArray addObject:[[ICPDFEICRInspectionPage2 alloc] initWithCertificate:self.certificate]];
    [pagesArray addObject:[[ICPDFEICRInspectionPage3 alloc] initWithCertificate:self.certificate]];
    [pagesArray addObject:[[ICPDFEICRPageFinal alloc] initWithCertificate:self.certificate]];
   }

  // Set page count on all pages
int pageNumber = 0;
for (ICCertificateComponent *page in pagesArray) {
    page.pageNumber.text = [NSString stringWithFormat:@"%d", ++pageNumber];
    page.pageCount.text = [NSString stringWithFormat:@"%d", pagesArray.count];
  }

   NSData *pdfData = [self createPdfWithPages:pagesArray];
  [self performSelectorOnMainThread:@selector(pdfDone:) withObject:pdfData waitUntilDone:YES];

  }
  }
     - (void)pdfDone:(NSData *)data
   {
self.pdfData = data;
[self.webView loadData:self.pdfData MIMEType:@"application/pdf" textEncodingName:@"utf-8" baseURL:nil];
[ICUtils removeProgressView];
 }

  - (NSData *)createPdfWithPages:(NSArray *)pages
  {
// Creates a mutable data object for updating with binary data, like a byte array

  NSMutableData *pdfData = [NSMutableData data];

  ICCertificateComponent *firstPage = [pages objectAtIndex:0];

   UIGraphicsBeginPDFContextToData(pdfData, firstPage.contentView.bounds, nil);

  for (int i = 0; i < pages.count; i++) {
    ICCertificateComponent *thisPage = [pages objectAtIndex:i];
    UIGraphicsBeginPDFPageWithInfo(thisPage.contentView.bounds, nil);

    CGContextRef pdfContext = UIGraphicsGetCurrentContext();
    [thisPage.contentView.layer renderInContext:pdfContext];
   }

 UIGraphicsEndPDFContext();

return pdfData;

}

2 个答案:

答案 0 :(得分:0)

您正在将所有PDF数据生成到内存数据结构中,这是一个坏主意。尝试使用UIGraphicsBeginPDFContextToFile将PDF数据首先写入文件。完成后,将其加载到Web视图中。

答案 1 :(得分:-2)

一些可能的方法:

  1. 的UITableView。每个单元格都有一个页面。 iOS要求您创建单元格,因此按需创建页面,并且只保留足以填满屏幕。问题是PDF页面的渲染需要很长时间,这会使滚动生涩。

  2. UICollectionView。相同但允许更多的灵活性,例如从左到右页面。

  3. CATiledLayer。与谷歌地图一样,您可以通过在后台渲染来平滑滚动。我发现,更复杂,实际上在显示文档的实践中并不是那么好。

  4. 为webView创建一个PDF文件进行渲染,而不是将所有页面渲染到内存中。该系统将处理内存,它将滚动顺利,没有人工制品。如果PDF页面没有变化,可能是你最好的选择。