2013-01-15 69 views
0

我有一个生成PDF文件的应用程序。由于用户能够添加页面,这些PDf可能很大,可能无限制,尽管通常是约。十。我遇到了iPhone 4用户在PDF生成阶段遇到问题的问题。一些调查工作显示,该应用程序内存不足。我可以重现这个问题如果我在iPhone 5上添加50页以上的页面,iPhone 4等上的页面少得多,而不是预期的模拟器上。由于内存不足导致应用程序崩溃

只是为了说明我的应用程序在生成PDF和崩溃时内存不足。

伊夫这里研究iPhone App Crashes due to Low Memory but works fine in simulator

这里Quartz PDF API Causing Out of Memory Crashes

有没有一种方法,我可以降低这种内存使用情况。我通过仪器运行它,这是我得到的,我不是一个有经验的程序员,所以不知道如何正确解释或解决这个问题。

enter image description here

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

if ([self.certificate.certificateType.title isEqualToString:@"Minor Works"]) { 
    [pagesArray addObject:[[ICPDFMinorWorksPage1 alloc] initWithCertificate:self.certificate]]; 
    [pagesArray addObject:[[ICPDFMinorWorksPage2 alloc] initWithCertificate:self.certificate]]; 

} else if ([self.certificate.certificateType.title isEqualToString:@"EIC"]) { 
    [pagesArray addObject:[[ICPDFEICPage1 alloc] initWithCertificate:self.certificate]]; 
    [pagesArray addObject:[[ICPDFEICPage2 alloc] initWithCertificate:self.certificate]]; 
    [pagesArray addObject:[[ICPDFEICPage3 alloc] initWithCertificate:self.certificate]]; 
    [pagesArray addObject:[[ICPDFEICPage4 alloc] initWithCertificate:self.certificate]]; 
    [pagesArray addObject:[[ICPDFEICPage5 alloc] initWithCertificate:self.certificate]]; 
    [self addDistributionBoardsToPagesArray:pagesArray]; 
    ICPDFEICPageFinal *pageFinal = [[ICPDFEICPageFinal alloc] initWithCertificate:self.certificate]; 
    pageFinal.pageNumber.text = [NSString stringWithFormat:@"%d", pagesArray.count+1]; 
    [pagesArray addObject:pageFinal]; 

} else if ([self.certificate.certificateType.title isEqualToString:@"Domestic EIC"]) { 
    [pagesArray addObject:[[ICPDFDomesticEICPage1 alloc] initWithCertificate:self.certificate]]; 
    [pagesArray addObject:[[ICPDFDomesticEICPage2 alloc] initWithCertificate:self.certificate]]; 
    [pagesArray addObject:[[ICPDFDomesticEICPage3 alloc] initWithCertificate:self.certificate]]; 
    [pagesArray addObject:[[ICPDFDomesticEICPage4 alloc] initWithCertificate:self.certificate]]; 
    [self addDistributionBoardsToPagesArray:pagesArray]; 
    [pagesArray addObject:[[ICPDFDomesticEICPageFinal alloc] initWithCertificate:self.certificate]]; 

} else 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); 
    // 
    // CGContextSetInterpolationQuality((__bridge CGContextRef)(thisPage), kCGInterpolationHigh); CGContextSetRenderingIntent((__bridge CGContextRef)(thisPage), kCGRenderingIntentDefault); 
    // 

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

UIGraphicsEndPDFContext(); 

return pdfData; 
} 

- (void)addDistributionBoardsToPagesArray:(NSMutableArray *)pagesArray 
{ 
int pageCount = pagesArray.count; 
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"createdAt" ascending:YES]; 
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; 
NSArray *boards = [self.certificate.distributionBoards sortedArrayUsingDescriptors:sortDescriptors]; 
for (DistributionBoard *thisBoard in boards) { 
    DebugLog(@"Creating a board page"); 
    ICPDFDistributionBoard *boardPage = [[ICPDFDistributionBoard alloc] initWithDistributionBoard:thisBoard]; 
    boardPage.pageNumber.text = [NSString stringWithFormat:@"%d", ++pageCount]; 
    DebugLog(@"Page number is %d", pageCount); 
    [pagesArray addObject:boardPage]; 

    NSSortDescriptor *circuitDescriptor = [[NSSortDescriptor alloc] initWithKey:@"createdAt" ascending:YES]; 
    NSArray *circuitDescriptors = [[NSArray alloc] initWithObjects:circuitDescriptor, nil]; 
    NSArray *circuits = [thisBoard.circuits sortedArrayUsingDescriptors:circuitDescriptors]; 

    //int circuitCount = circuits.count; 
    ICPDFCircuitDetails *circuitDetails = boardPage.circuitDetails; 

    int circuitCount = 0; 
    for (Circuit *thisCircuit in circuits) { 
     circuitCount++; 
     if (circuitCount > 16) { 
      // Add an extension page 
      DebugLog(@"Adding an extension sheet"); 
      circuitCount = 1; 
      ICPDFDistributionBoardExtension *boardExtension = [[ICPDFDistributionBoardExtension alloc] initWithDistributionBoard:thisBoard]; 
      [pagesArray addObject:boardExtension]; 
      boardExtension.pageNumber.text = [NSString stringWithFormat:@"%d", ++pageCount]; 
      circuitDetails = boardExtension.circuitDetails; 
     } 
     NSString *key = [NSString stringWithFormat:@"circuitRow%d", circuitCount]; 
     ICCircuitRow *circuitRow = [circuitDetails valueForKey:key]; 
     [circuitRow populateFromCircuit:thisCircuit]; 
     } 
    } 
} 

- (void)addObservationsToPagesArray:(NSMutableArray *)pagesArray 
{ 
int pageCount = pagesArray.count; 
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"createdAt" ascending:YES]; 
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; 
NSArray *observations = [self.certificate.observations sortedArrayUsingDescriptors:sortDescriptors]; 

ICPDFObservations *observationsPage = [[ICPDFObservations alloc] initWithCertificate:self.certificate]; 
if (observations.count > 28) { 
    observationsPage.additionalObservations.text = @"\u2714"; 
    observationsPage.additionalNotesAttachedOrToFollowRef.text = @"Attached"; 
} 
observationsPage.pageNumber.text = [NSString stringWithFormat:@"%d", ++pageCount]; 
DebugLog(@"Page number is %d", pageCount); 
[pagesArray addObject:observationsPage]; 

ICObservationTable *observationTable = observationsPage.observationTable; 

int observationCount = 0; 
for (Observation *observation in observations) { 
    observationCount++; 
    if (observationCount > 28) { 
     // Add an extension page 
     DebugLog(@"Adding an extension sheet"); 
     observationCount = 1; 
     ICPDFObservationsExtension *observationsExtension = [[ICPDFObservationsExtension alloc] initWithCertificate:self.certificate]; 
     [pagesArray addObject:observationsExtension]; 
     observationTable = observationsExtension.observationTable; 
    } 
    NSString *key = [NSString stringWithFormat:@"observationRow%d", observationCount]; 
    ICObservationRow *observationRow = [observationTable valueForKey:key]; 
    [observationRow populateFromObservation:observation]; 
    } 

} 

回答

0

用仪器检查,由于保留,但不被泄漏内存泄漏和记忆丧失。后者是尚未使用的内存,仍然指向。在乐器上的分配乐器中使用Heapshot。

至于如何使用Heapshot查找内存creap,请参见:bbum blog

基本上有方法是运行仪器分配工具,取heapshot,运行代码的直觉和另一heapshot重复3或4次。这将指示在迭代过程中分配并未释放的内存。

为了弄清楚结果是否披露了个别分配。

如果你需要看到保留,发布和自动释放出现一个对象使用仪器:在仪器

运行,在设定“记录的引用计数”关于分配(你必须停止记录设置选项)。导致选择器运行,停止录制,在那里搜索ivar(datePickerView),向下钻取,您将能够看到所有保留,发布和自动释放发生的位置。

+0

感谢您对仪器的建议。对于我来说,这仍然没有多大意义,因为我无法将其解释为故障查找。任何建议重新我发布的代码,如何减少其生成PDF时的内存爬升? – JSA986

相关问题