2013-01-15 106 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

相關問題