应用程序因内存不足而崩溃

时间:2013-01-15 00:09:54

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

我有一个生成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];
  }

 }

1 个答案:

答案 0 :(得分:0)

使用仪器检查由于保留但未泄漏的内存导致的泄漏和内存丢失。后者是未使用的内存,仍然指向。在仪器上的分配工具中使用快照。

如何使用“快照”查找内存褶皱,请参阅:bbum blog

基本上有一种方法是运行仪器分配工具,获取快照,运行代码直观和另一个快照重复3或4次。这将指示在迭代期间分配但未释放的内存。

要弄清楚披露的结果,以查看个别分配。

如果您需要查看对象使用仪器的保留,释放和自动释放的位置:

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