我有一个生成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
有没有办法可以减少这种内存使用量。我通过乐器运行它,这是我得到的,我不是一个有经验的程序员,所以不知道如何正确解释或解决这个问题。
- (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 :(得分:0)
使用仪器检查由于保留但未泄漏的内存导致的泄漏和内存丢失。后者是未使用的内存,仍然指向。在仪器上的分配工具中使用快照。
如何使用“快照”查找内存褶皱,请参阅:bbum blog
基本上有一种方法是运行仪器分配工具,获取快照,运行代码直观和另一个快照重复3或4次。这将指示在迭代期间分配但未释放的内存。
要弄清楚披露的结果,以查看个别分配。
如果您需要查看对象使用仪器的保留,释放和自动释放的位置:
在仪器中运行,在分配中设置“记录参考计数”(您必须停止记录以设置选项)。导致选择器运行,停止记录,搜索那里的ivar(datePickerView),向下钻取,你将能够看到所有保留,释放和自动释放发生的位置。