Ios 创建PDF时内存警告和崩溃

Ios 创建PDF时内存警告和崩溃,ios,objective-c,cocoa-touch,memory-management,Ios,Objective C,Cocoa Touch,Memory Management,生成大型PDF时,我的应用程序会收到内存警告,然后在生成PDF的过程中崩溃。PDF被绘制到web视图中,当页面超过一定数量(取决于设备)时,我会耗尽内存 到目前为止,我对这件事的研究让我明白,我需要: 将UIGraphicsBeginPDFContextToData更改为IGraphicsBeginPDFContextToFile 创建临时文件的合理路径 把这个给函数 将文件交给webview以加载 完成后删除该文件 问题是,虽然我认为我在原则上掌握了它,但我不知道如何去实现它,或者完全理解它以

生成大型PDF时,我的应用程序会收到内存警告,然后在生成PDF的过程中崩溃。PDF被绘制到web视图中,当页面超过一定数量(取决于设备)时,我会耗尽内存

到目前为止,我对这件事的研究让我明白,我需要:

UIGraphicsBeginPDFContextToData
更改为
IGraphicsBeginPDFContextToFile

  • 创建临时文件的合理路径

  • 把这个给函数

  • 将文件交给webview以加载

  • 完成后删除该文件

  • 问题是,虽然我认为我在原则上掌握了它,但我不知道如何去实现它,或者完全理解它以便在代码中实现它。这件事上的建议很受欢迎

    我也愿意接受任何其他方法来阻止内存崩溃

    @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;
    }