使用Cocoa,NSPrintOperation,如何从NSView中的文本正确创建PDF文件?

时间:2015-05-14 03:11:42

标签: cocoa pdf-generation nsview nsprintoperation

使用NSPrintOperation,如何从NSView中的文本正确创建PDF文件?

* *通知我发现了一个在底部显示的工作 *

我做了什么: 1.将文本放入NSTextView。

- (NSTextView *)printableViewWithRecipe:(Recipe *)recipe
{

[_printView setString:@""];
[_printView setTextColor:[NSColor textColor]];
[_printView setFont:[NSFont userFontOfSize:0]];
NSDictionary    *titleAttr;
_printView = [[NSTextView alloc] initWithFrame:[[self printInfo] imageablePageBounds]];
[_printView setVerticallyResizable:YES];
[_printView setHorizontallyResizable:NO];

// Begin to ADD THE TEXT
[[_printView textStorage] beginEditing];

// Set the attributes for the title
[[_printView textStorage] beginEditing];
titleAttr =
[NSDictionary dictionaryWithObject:[(AppDelegate*)[[NSApplication sharedApplication] delegate] tableFont] forKey:NSFontAttributeName];

// Add the title
[
 [_printView textStorage] appendAttributedString:
 [[NSAttributedString alloc] initWithString:[recipe name]  attributes:titleAttr ]
];

// Create a couple returns between the title and the body
[[_printView textStorage] appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n\n"]];

// Add the body text
if([[recipe ingredients] length] )
    [[_printView textStorage] appendAttributedString: [ [NSAttributedString alloc]
                                                      initWithString:[recipe ingredients] attributes:titleAttr]];
// Create a couple returns between the ingredients and the directions
[[_printView textStorage] appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n\n"]];
if([[recipe directions] length] )
    [[_printView textStorage] appendAttributedString: [ [NSAttributedString alloc]
                                                      initWithString:[recipe directions] attributes:titleAttr]];
// Create a couple returns between the directions and the comments
[[_printView textStorage] appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n\n"]];
if([[recipe comments] length] )
    [[_printView textStorage] appendAttributedString: [ [NSAttributedString alloc]
                                                      initWithString:[recipe comments] attributes:titleAttr]];
// Center the title
[_printView setAlignment:NSCenterTextAlignment range:NSMakeRange(0, [[recipe name] length])];

[[_printView textStorage] endEditing];

return _printView;

} // end printableViewForRecipe

2.尝试使用以下方法从TextView的文本创建PDF文件:

- (PDFDocument *)exportPDFfromView:(NSTextView*)textView  fileNumber:(NSUInteger)fileNumber
{ 
    NSPrintInfo *printInfo;
    NSPrintInfo *sharedInfo;
    NSPrintOperation *printOp;
    NSMutableDictionary *printInfoDict;
    NSMutableDictionary *sharedDict;
    sharedInfo = [NSPrintInfo sharedPrintInfo];
    sharedDict = [sharedInfo dictionary];
    printInfoDict = [NSMutableDictionary dictionaryWithDictionary: sharedDict];
    [printInfoDict setObject:NSPrintSaveJob forKey:NSPrintJobDisposition];
    NSString *tempFileName = [NSString stringWithFormat:@"%@_file_%lu.pdf", [[NSProcessInfo processInfo] globallyUniqueString], fileNumber];
    NSURL *poTempfileURL = [_tempDirectoryURL URLByAppendingPathComponent:tempFileName];
    [printInfoDict setObject:poTempfileURL forKey:NSPrintJobSavingURL];
    printInfo = [[NSPrintInfo alloc] initWithDictionary:printInfoDict];//1
    [printInfo setHorizontalPagination: NSAutoPagination];//2
    [printInfo setVerticalPagination: NSAutoPagination];//3
    [printInfo setVerticallyCentered:NO];//4

    printOp = [NSPrintOperation printOperationWithView:textView printInfo:printInfo];//5
    [printOp setShowsPrintPanel:NO];
    [printOp setShowsProgressPanel:NO];//6
    DLog(@"poTempfileURL=%@",poTempfileURL);

    BOOL didRunOK = [printOp runOperation];//7
    BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:[poTempfileURL path]];
    DLog(@"poTempfileURL=%@",poTempfileURL);
    DLog(@"didRunOK=%lu\nfileExists=%lu",didRunOK,exists);
    PDFDocument *doc = [[PDFDocument alloc] initWithURL:poTempfileURL];

    return doc;
}
  1. 运行以下代码:

    [self tempDirectoryURL];// invoke getter
    NSLog(@"_tempDirectoryURL=%@",_tempDirectoryURL);
    
    _tempDirectoryURL=file:///var/folders/8p/c2x7m74j1wzdf92jy770zx500000gn/T/com.DrummingGrouse.HungryMe/ 
    
  2. Getter如下:

    - (NSURL *)tempDirectoryURL { //getter
        NSURL *tempURL;
        if(!_tempDirectoryURL){
            tempURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]] isDirectory:YES];
            _tempDirectoryURL = tempURL;
        }
        return _tempDirectoryURL;
    }   
    
    1. 运行此代码后:

      BOOL didRunOK = [printOp runOperation]; // 7

      BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:[poTempfileURL path]];  DLOG(@" didRunOK =%录\ nfileExists =%鲁",didRunOK,存在);  DLOG(@" poTempfileURL =%@",poTempfileURL);

    2. 我希望在以下位置创建PDF:poTempfileURL,其值为:      poTempfileURL =文件:///var/folders/8p/c2x7m74j1wzdf92jy770zx500000gn/T/com.DrummingGrouse.HungryMe/884B9B4C-907B-489E-869B-B5EFE7A11B47-1821-000016435C134E56/7A196040-0D81-496D-B9F3-BF0B855F6BBC-1821-0000164A9446040F_file_0 .PDF

      控制台显示:

       didRunOK=1
       fileExists=1
      
      1. 当以下代码行运行时:

        BOOL didRunOK = [printOp runOperation]; // 7

      2. printOp的printInfo内容为:

        {
            NSBottomMargin = 90;
            NSCopies = 1;
            NSDestinationFormat = "application/pdf";
            NSDetailedErrorReporting = 0;
            NSFaxNumber = "";
            NSFirstPage = 1;
            NSHorizonalPagination = 0;
            NSHorizontallyCentered = 0;
            NSJobDisposition = NSPrintSaveJob;
            NSJobSavingFileNameExtensionHidden = 0;
            NSJobSavingURL = "file:///var/folders/8p/c2x7m74j1wzdf92jy770zx500000gn/T/com.DrummingGrouse.HungryMe/2687B4CD-6ABF-4826-B8F8-3D536FFACA66-1362-00001DEFA0B13D70/1F0483BF-00B4-4F65-A3C7-C4824F53C03E-1362-00001DF033AAD968_file_0.pdf";
            NSLastPage = 2147483647;
            NSLeftMargin = 72;
            NSMustCollate = 1;
            NSOrientation = 0;
            NSPagesAcross = 1;
            NSPagesDown = 1;
            NSPaperName = "na-letter";
            NSPaperSize = "NSSize: {612, 792}";
            NSPrintAllPages = 1;
            NSPrintProtected = 0;
            NSPrintSelectionOnly = 0;
            NSPrintTime = "0000-12-30 00:00:00 +0000";
            NSPrinter = "{\n    \"Device Description\" =     {\n        NSDeviceIsPrinter = YES;\n    };\n    \"Language Level\" = 3;\n    Name = \"HP DESKJET 840C @ Mark\\U2019s Mac Pro\";\n    Type = \"Generic PCL Laser Printer\";\n}";
            NSPrinterName = "HP DESKJET 840C @ Mark\U2019s Mac Pro";
            NSRightMargin = 72;
            NSSavePath = "/var/folders/8p/c2x7m74j1wzdf92jy770zx500000gn/T/com.DrummingGrouse.HungryMe/2687B4CD-6ABF-4826-B8F8-3D536FFACA66-1362-00001DEFA0B13D70/1F0483BF-00B4-4F65-A3C7-C4824F53C03E-1362-00001DF033AAD968_file_0.pdf";
            NSScalingFactor = 1;
            NSTopMargin = 90;
            NSVerticalPagination = 0;
            NSVerticallyCentered = 0;
        }
        

        在Xcode中:po [[textView textStorage] string]生成以下标记为的文本:

         /// BEGIN NSTextView TEXT ///
        

        在我打开位于poTempFileURL的文件时在Finder中,    在预览中,该文件有四个页面(它应该只有一个页面),    并且在预览中似乎是一个空的PDF文件。

        当我打开这个" PDF"文件在TextEdit中,该文件包含    下面的内容标记为:/// BEGIN TEXT PDF Tempfile ///

        我需要做些什么来制作一个适当的" PDF文件?我无法获得可以在预览中打开和阅读的PDF。

        po [doc pageCount]显示" 4"

        /// BEGIN NSTextView TEXT /// - po [[textView textStorage] string]

        French Toast
        
        [French Toast]
        preptime 0:03 cooktime 0:08 serves:1-2
        
        egg   1     
        milk   3/4  cup 
        ground cinnamon   1/8  tsp  (optional)
        best bread   2  slices  
        butter   4  tsp (two per side)
        maple syrup     (to taste)
        
        
        [French Toast]
        
        1. Add egg to a bowl and beat with a fork. 
        
        2. Add milk and cinnamon to egg and beat briefly.
        
        3. Heat heavy skillet to medium high. Add 2 tsp butter. 
        
        4. Dip bread slice halves in batter and brown in skillet. Flip and add additional butter. Brown and serve with syrup.
        
        Serve with pork sausage, chorizo or bacon.
        

        ///结束NSTextView TEXT ///

        /// BEGIN TEXT PDF Tempfile ///

        %PDF-1.3
        %ƒÂÚÂÎßÛ†–ƒ∆
        4 0 obj
        << /Length 5 0 R /Filter /FlateDecode >>
        stream
        x+T�Á�„
        endstream
        endobj
        5 0 obj
        11
        endobj
        2 0 obj
        << /Type /Page /Parent 3 0 R /Resources 6 0 R /Contents 4 0 R /MediaBox [0 0 612 792]
        >>
        endobj
        6 0 obj
        << /ProcSet [ /PDF ] >>
        endobj
        8 0 obj
        << /Length 9 0 R /Filter /FlateDecode >>
        stream
        x+T�Á�„
        endstream
        endobj
        9 0 obj
        11
        endobj
        7 0 obj
        << /Type /Page /Parent 3 0 R /Resources 10 0 R /Contents 8 0 R /MediaBox [0 0 612 792]
        >>
        endobj
        10 0 obj
        << /ProcSet [ /PDF ] >>
        endobj
        12 0 obj
        << /Length 13 0 R /Filter /FlateDecode >>
        stream
        x+T�Á�„
        endstream
        endobj
        13 0 obj
        11
        endobj
        11 0 obj
        << /Type /Page /Parent 3 0 R /Resources 14 0 R /Contents 12 0 R /MediaBox
        [0 0 612 792] >>
        endobj
        14 0 obj
        << /ProcSet [ /PDF ] >>
        endobj
        16 0 obj
        << /Length 17 0 R /Filter /FlateDecode >>
        stream
        x+T�Á�„
        endstream
        endobj
        17 0 obj
        11
        endobj
        15 0 obj
        << /Type /Page /Parent 3 0 R /Resources 18 0 R /Contents 16 0 R /MediaBox
        [0 0 612 792] >>
        endobj
        18 0 obj
        << /ProcSet [ /PDF ] >>
        endobj
        3 0 obj
        << /Type /Pages /MediaBox [0 0 612 792] /Count 4 /Kids [ 2 0 R 7 0 R 11 0 R
        15 0 R ] >>
        endobj
        19 0 obj
        << /Type /Catalog /Pages 3 0 R >>
        endobj
        20 0 obj
        (Untitled)
        endobj
        21 0 obj
        (Mac OS X 10.10.3 Quartz PDFContext)
        endobj
        22 0 obj
        (HungryMe)
        endobj
        23 0 obj
        (D:20150513191029Z00'00')
        endobj
        24 0 obj
        ()
        endobj
        25 0 obj
        [ ]
        endobj
        1 0 obj
        << /Title 20 0 R /Producer 21 0 R /Creator 22 0 R /CreationDate 23 0 R /ModDate
        23 0 R /Keywords 24 0 R /AAPL:Keywords 25 0 R >>
        endobj
        xref
        0 26
        0000000000 65535 f 
        0000001363 00000 n 
        0000000125 00000 n 
        0000001022 00000 n 
        0000000022 00000 n 
        0000000107 00000 n 
        0000000229 00000 n 
        0000000371 00000 n 
        0000000268 00000 n 
        0000000353 00000 n 
        0000000476 00000 n 
        0000000622 00000 n 
        0000000516 00000 n 
        0000000603 00000 n 
        0000000729 00000 n 
        0000000875 00000 n 
        0000000769 00000 n 
        0000000856 00000 n 
        0000000982 00000 n 
        0000001125 00000 n 
        0000001175 00000 n 
        0000001202 00000 n 
        0000001255 00000 n 
        0000001282 00000 n 
        0000001324 00000 n 
        0000001343 00000 n 
        trailer
        << /Size 26 /Root 19 0 R /Info 1 0 R /ID [ <1abd1092f1d909274c086bf0f90d6200>
        <1abd1092f1d909274c086bf0f90d6200> ] >>
        startxref
        1507
        %%EOF
        

        ///结束文本PDF Tempfile

        如果我重做方法exportPDFfromView:fileNumber:这样,

        - (PDFDocument *)exportPDFfromView:(NSTextView*)textView  fileNumber:(NSUInteger)fileNumber
        {
            NSString *tempFileName = [NSString stringWithFormat:@"%@_file_%lu.pdf", [[NSProcessInfo processInfo] globallyUniqueString], fileNumber];
            NSURL *poTempfileURL = [_tempDirectoryURL URLByAppendingPathComponent:tempFileName];
            DLog(@"poTempfileURL=%@",poTempfileURL);
        
            NSRect r = [textView bounds];
            NSData *data = [textView dataWithPDFInsideRect:r];
            [data writeToFile:poTempfileURL.path atomically:YES];
            PDFDocument *doc2 = [[PDFDocument alloc] initWithURL:poTempfileURL];
            DLog(@"doc2.pageCount=%lu",doc2.pageCount);
        
            ...
        
            return doc2;
        }
        

        当我在URL poTempfileURL查看生成的PDF文件时,它有一个页面,这是正确的。但同样是PDF 预览中不显示任何文本。如果我看到这个&#34; PDF&#34;使用TextEdit,内容如下。

        %PDF-1.3
        %ƒÂÚÂÎßÛ†–ƒ∆
        4 0 obj
        << /Length 5 0 R /Filter /FlateDecode >>
        stream
        x+TÁ„
        endstream
        endobj
        5 0 obj
        11
        endobj
        2 0 obj
        << /Type /Page /Parent 3 0 R /Resources 6 0 R /Contents 4 0 R /MediaBox [0 0 576 734]
        >>
        endobj
        6 0 obj
        << /ProcSet [ /PDF ] >>
        endobj
        3 0 obj
        << /Type /Pages /MediaBox [0 0 576 734] /Count 1 /Kids [ 2 0 R ] >>
        endobj
        7 0 obj
        << /Type /Catalog /Pages 3 0 R >>
        endobj
        8 0 obj
        (Mac OS X 10.10.3 Quartz PDFContext)
        endobj
        9 0 obj
        (D:20150517134359Z00'00')
        endobj
        1 0 obj
        << /Producer 8 0 R /CreationDate 9 0 R /ModDate 9 0 R >>
        endobj
        xref
        0 10
        0000000000 65535 f 
        0000000493 00000 n 
        0000000125 00000 n 
        0000000268 00000 n 
        0000000022 00000 n 
        0000000107 00000 n 
        0000000229 00000 n 
        0000000351 00000 n 
        0000000400 00000 n 
        0000000452 00000 n 
        trailer
        << /Size 10 /Root 7 0 R /Info 1 0 R /ID [ <d86abf98c49359ba2092ad602722f659>
        <d86abf98c49359ba2092ad602722f659> ] >>
        startxref
        565
        %%EOF
        

        ! ! ! !

        我找到了一个解决方法,可以让我到达我想去的地方。这仍然没有向我解释为什么我看似无休止地尝试使用

            + (NSPrintOperation *)printOperationWithView:(NSView *)aView
                                       printInfo:(NSPrintInfo *)aPrintInfo
        

        失败。

        该解决方法生成可在预览中查看的多页PDF文件。

        我希望这对其他人有用。

        - (void)testQuartz:(NSData *)pdfDocumentData savePath:(NSString*)savePath
        {
           //Create the pdf document reference
           CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData((CFDataRef)pdfDocumentData);
           CGPDFDocumentRef document = CGPDFDocumentCreateWithProvider(dataProvider);
        
           //Create the pdf context
           CGPDFPageRef page = CGPDFDocumentGetPage(document, 1); //Pages are numbered starting at 1
           CGRect pageRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
           CFMutableDataRef mutableData = CFDataCreateMutable(NULL, 0);
        
           //NSLog(@"w:%2.2f, h:%2.2f",pageRect.size.width, pageRect.size.height);
           CGDataConsumerRef dataConsumer = CGDataConsumerCreateWithCFData(mutableData);
           CGContextRef pdfContext = CGPDFContextCreate(dataConsumer, &pageRect, NULL);
        
        
           if (CGPDFDocumentGetNumberOfPages(document) > 0)
           {
              //Draw the page onto the new context
              //page = CGPDFDocumentGetPage(document, 1); //Pages are numbered starting at 1
        
              CGPDFContextBeginPage(pdfContext, NULL);
              CGContextDrawPDFPage(pdfContext, page);
              CGPDFContextEndPage(pdfContext);
           }
           else
           {
              NSLog(@"Failed to create the document");
           }
        
           CGContextRelease(pdfContext); //Release before writing data to disk.
        
           //Write to disk
           [(__bridge NSData *)mutableData writeToFile:savePath atomically:YES];
        
           //Clean up
           CGDataProviderRelease(dataProvider); //Release the data provider
           CGDataConsumerRelease(dataConsumer);
           CGPDFDocumentRelease(document);
           CFRelease(mutableData);
        }
        
        
        - (PDFDocument *)exportPDFfromView:(NSTextView*)textView  fileNumber:(NSUInteger)fileNumber
        {
            NSString *tempFileName = [NSString stringWithFormat:@"%@_file_%lu.pdf", [[NSProcessInfo processInfo] globallyUniqueString], fileNumber];
            NSURL *poTempfileURL = [_tempDirectoryURL URLByAppendingPathComponent:tempFileName];
            DLog(@"poTempfileURL=%@",poTempfileURL);
        
            NSRect r = [textView bounds];
            NSData *data = [textView dataWithPDFInsideRect:r];
        
           [ self testQuartz:(NSData *)data savePath:poTempfileURL.path ];
        
            ...
        
            return aDoc;
        }
        

        如果你像我一样,想要发表一篇PDF文章,比如说文章,都是从单个PDF页面顶部开始,你可能会想要以下内容从临时输入文档中取出页面将它们全部移动到单个输出PDF中。

            NSUInteger pageCountDocZero = [[inputDocuments objectAtIndex:0] pageCount];
            NSUInteger pageIndex = pageCountDocZero;
            for (PDFDocument *document in inputDocuments) {
                for (NSUInteger j = 0; j < [document pageCount]; j++) {
                    PDFPage *page = [document pageAtIndex:j];
                    DLog(@"Inserting pageIndex:%lu i.e inputPage:%lu of %lu",pageIndex,j+1,[document pageCount]);
                    [outputDocument insertPage:page atIndex:pageIndex++];
                }
            }
        

0 个答案:

没有答案