Ios 创建PDF时内存警告和崩溃
生成大型PDF时,我的应用程序会收到内存警告,然后在生成PDF的过程中崩溃。PDF被绘制到web视图中,当页面超过一定数量(取决于设备)时,我会耗尽内存 到目前为止,我对这件事的研究让我明白,我需要: 将Ios 创建PDF时内存警告和崩溃,ios,objective-c,cocoa-touch,memory-management,Ios,Objective C,Cocoa Touch,Memory Management,生成大型PDF时,我的应用程序会收到内存警告,然后在生成PDF的过程中崩溃。PDF被绘制到web视图中,当页面超过一定数量(取决于设备)时,我会耗尽内存 到目前为止,我对这件事的研究让我明白,我需要: 将UIGraphicsBeginPDFContextToData更改为IGraphicsBeginPDFContextToFile 创建临时文件的合理路径 把这个给函数 将文件交给webview以加载 完成后删除该文件 问题是,虽然我认为我在原则上掌握了它,但我不知道如何去实现它,或者完全理解它以
UIGraphicsBeginPDFContextToData
更改为IGraphicsBeginPDFContextToFile
@interface ICPDFPreviewController ()
@property (nonatomic, strong) Certificate *certificate;
@property (nonatomic, strong) NSData *pdfData;
@property (nonatomic) BOOL viewHasUnloaded;
- (void)generatePdf;
- (void)pdfDone:(NSData *)data;
- (NSData *)createPdfWithPages:(NSArray *)pages;
@end
@implementation ICPDFPreviewController
@synthesize certificate=_certificate;
@synthesize scrollView=_scrollView;
@synthesize webView=_webView;
@synthesize pdfData=_pdfData;
@synthesize viewHasUnloaded=_viewHasUnloaded;
- (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);
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];
}
}
}
@接口ICPDFPreviewController()
@属性(非原子、强)证书*证书;
@属性(非原子,强)NSData*pdfData;
@属性(非原子)BOOL viewHasUnload;
-(无效)生成EPDF;
-(无效)pdfDone:(NSData*)数据;
-(NSData*)createPdfWithPages:(NSArray*)页;
@结束
@ICPDFPreviewController的实现
@综合证书=_证书;
@综合滚动视图=_滚动视图;
@综合网络视图=_网络视图;
@合成pdfData=_pdfData;
@综合ViewHasUnload=\u ViewHasUnload;
-(无效)生成EPDF
{
NSMutableArray*页面数组=[NSMutableArray];
如果([self.certificate.certificateType.title isEqualToString:@“次要工程”]){
[pagesArray addObject:[[ICPDFMinorWorksPage1 alloc]initWithCertificate:self.certificate]];
[pagesArray addObject:[[ICPDFMinorWorksPage2 alloc]initWithCertificate:self.certificate]];
}else if([self.certificate.certificateType.title IsequalString:@“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 IsequalString:@“国内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 IsequalString:@“EICR”]){
[pagesArray addObject:[[ICPDFEICRPage1 alloc]initWithCertificate:self.certificate]];
[pagesArray addObject:[[ICPDFEICRPage2 alloc]initWithCertificate:self.certificate]];
[自助添加ObservationsTopageSarray:pagesArray];
[self-addDistributionBoardsToPagesArray:pagesArray];
[pagesArray addObject:[[ICPDFEICRInspection alloc]initWithCertificate:self.certificate]];
[pagesArray addObject:[[ICPDFEICInspectionPage1 alloc]initWithCertificate:self.certificate]];
[pagesArray addObject:[[ICPDFEICInspectionPage2 alloc]initWithCertificate:self.certificate]];
[pagesArray addObject:[[ICPDFEICInspectionPage3 alloc]initWithCertificate:self.certificate]];
[pagesArray addObject:[[ICPDFEICRPageFinal alloc]initWithCertificate:self.certificate]];
}
//设置所有页面的页数
int pageNumber=0;
用于(ICCertificateComponent*第页中的第页){
page.pageNumber.text=[NSString stringWithFormat:@“%d”,++pageNumber];
page.pageCount.text=[NSString stringWithFormat:@“%d”,pagesArray.count];
}
NSData*pdfData=[self-createPdfWithPages:pagesArray];
[self-performSelectorOnMainThread:@selector(pdfDone:)with object:pdfData waituntldone:YES];
}
-(无效)pdfDone:(NSData*)数据
{
self.pdfData=数据;
[self.webView加载数据:self.pdfData MIMEType:@“application/pdf”text编码名称:@“utf-8”baseURL:nil];
[ICUtils removeProgressView];
}
-(NSData*)createPdfWithPages:(NSArray*)页面
{
//创建一个可变数据对象,以便使用二进制数据(如字节数组)进行更新
NSMutableData*pdfData=[NSMutableData];
ICCertificateComponent*firstPage=[页面对象索引:0];
UIGraphicsBeginPDFContextToData(pdfData,firstPage.contentView.bounds,nil);
对于(int i=0;i 2013-02-08 10:38:35.475 iCertifi[5772:907] Received memory warning.
2013-02-08 10:38:35.477 iCertifi[5772:907] <ICPDFPreviewController: 0x1eb28930> didReceiveMemoryWarning
// start pdf document using default page size (CGRectZero)
UIGraphicsBeginPDFContextToFile(pdfFileName, CGRectZero, nil);
// then loop through your content drawing it one page at a time.
for ( page p in pages ) // or whatever you are cycling over for page content
{
UIGraphicsBeginPDFPage(); // or UIGraphicsBeginPDFPageWithInfo
// do your drawing to the page here by drawing to the current graphics context.
// if you are setting up transforms and such
}
// close out the last page and the document both
UIGraphicsEndPDFContext();
- (IBAction)buttonPress:(id)sender
{
[self createPDFData:[self getPDFFileName]];
}
-(NSString *)getPDFFileName
{
NSString * fileName = @"Info.PDF";
NSArray *arrayPaths =
NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory,
NSUserDomainMask,
YES);
NSString * path = [arrayPaths objectAtIndex:0];
NSString *pdfFileName = [path stringByAppendingPathComponent:fileName];
NSLog(@"path : %@",path);
NSLog(@"pdf file name : %@",pdfFileName);
return pdfFileName;
}
-(void)showPDFFile
{
UIWebView * webView = [[UIWebView alloc] initWithFrame:CGRectMake(0,44,1024,748)];
NSURL *url = [NSURL fileURLWithPath:[self getPDFFileName]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[webView setScalesPageToFit:YES];
[webView loadRequest:request];
[self.view addSubview:webView];
}
-(void)createPDFData:(NSString *)fileName{
CGRect pageFrame = CGRectMake(0,0,768,1024);
UIGraphicsBeginPDFContextToFile(fileName, CGRectZero, nil);//This starts drawing a pdf to file named "filename" UIGraphicsBeginPDFPageWithInfo(pageFrame, nil);//For each new page call this
UIGraphicsGetCurrentContext();
UIGraphicsBeginPDFPageWithInfo(pageFrame, nil);//Next or new Page
NSString * timeLabel = [NSString stringWithFormat:@"Some text"];
[timeLabel drawInRect:CGRectMake(200, 200, 428, 44) withFont:[UIFont boldSystemFontOfSize:10] lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentLeft];
UIGraphicsEndPDFContext();
[self showPDFFile];
}
for (int i = 0; i < pages.count; i++) {
// notice this line
@autureleasepool
{
ICCertificateComponent *thisPage = [pages objectAtIndex:i];
UIGraphicsBeginPDFPageWithInfo(thisPage.contentView.bounds, nil);
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
[thisPage.contentView.layer renderInContext:pdfContext];
}
}
...
CGPoint savedContentOffset;
CGRect savedFrame;
NSMutableData * pdfData;
int pdfOffset;
NSTimer *timer;
...
- (void)preparePdf {
CGFloat height = aWebView.scrollView.contentSize.height;
CGRect screenRect = [[UIScreen mainScreen] bounds];
int pageHeight = screenRect.size.height;
savedContentOffset = aWebView.scrollView.contentOffset;
savedFrame = aWebView.frame;
pdfData=[NSMutableData data];
aWebView.scrollView.contentOffset = CGPointZero;
aWebView.frame = CGRectMake(aWebView.frame.origin.x,aWebView.frame.origin.y,aWebView.frame.size.width,pageHeight);
UIGraphicsBeginPDFContextToData(pdfData, aWebView.frame, nil);
NSLog(@"pageHeight = %d", pageHeight);
pdfOffset = 0;
timer = [NSTimer scheduledTimerWithTimeInterval: 0.4
target: self
selector: @selector(printPdfPage:)
userInfo: nil
repeats: YES];
}
- (void) printPdfPage: (NSTimer*) timer {
CGFloat height = aWebView.scrollView.contentSize.height;
CGRect screenRect = [[UIScreen mainScreen] bounds];
int pageHeight = screenRect.size.height;
NSLog(@"pdfOffset = %d", pdfOffset);
UIGraphicsBeginPDFPage();
[aWebView drawViewHierarchyInRect:CGRectMake(0, 0, screenRect.size.width, pageHeight) afterScreenUpdates:YES];
pdfOffset += pageHeight;
aWebView.scrollView.contentOffset = CGPointMake(0, pdfOffset);
if (pdfOffset > height) {
[timer invalidate];
NSLog(@"pdf data size: %ld", pdfData.length);
[self emailPdf: pdfData];
}
}
- (void) emailPdf: (NSMutableData*) pdfData {
// finally end the PDF context.
UIGraphicsEndPDFContext();
aWebView.scrollView.contentOffset = savedContentOffset;
aWebView.frame = savedFrame;
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
mailer.mailComposeDelegate = self;
[mailer setSubject:[@"iPad Screenshot " stringByAppendingString:[self getDate]]];
[mailer addAttachmentData:pdfData mimeType:@"application/pdf" fileName:[[self getDate] stringByAppendingPathExtension:@"pdf"]];
NSString *emailBody = @"";
[mailer setMessageBody:emailBody isHTML:NO];
[self presentViewController:mailer animated:YES completion:nil];
if ([SVProgressHUD isVisible]) {
[SVProgressHUD showSuccessWithStatus:@"Screenshot prepared."];
}
pdfData = nil;
timer = nil;
}