【问题标题】:iOS: Reading contents of PDF FileiOS:阅读 PDF 文件的内容
【发布时间】:2013-05-19 07:24:51
【问题描述】:

通过访问 Quartz 2D 编程指南和 SO 上的一些帖子,我拼凑了一些代码来读取 PDF 文件的内容。我认为它在 PDF 扫描仪部分失败了。当我释放扫描仪时,应用程序崩溃并出现以下错误:

avi(2282,0x3de7bb88) malloc: *** error for object 0x693f7c0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug

我正在通过电子邮件附件打开 PDF 文件。我知道它至少可以识别文件,因为我可以获得页数。有人可以看看我下面的代码,看看我的错误发生在哪里吗?谢谢。

- (void) readPDFFile:(NSURL *)PDFURL {

    //make a pdf document and point it to the url of our pdf file
    CGPDFDocumentRef pdfDocument;
    pdfDocument = CGPDFDocumentCreateWithURL((__bridge CFURLRef)(PDFURL));

    //release the url
    CFRelease((__bridge CFTypeRef)(PDFURL));


    if (pdfDocument) {

        //get page count
        int pageCount = CGPDFDocumentGetNumberOfPages (pdfDocument);

        //
        if (pageCount > 0) {

            //set up operator table
            CGPDFOperatorTableRef pdfOpTable;
            pdfOpTable = CGPDFOperatorTableCreate();

            //call backs for Op Table
            CGPDFOperatorTableSetCallback (pdfOpTable, "MP", &op_MP);
            CGPDFOperatorTableSetCallback (pdfOpTable, "DP", &op_DP);
            CGPDFOperatorTableSetCallback (pdfOpTable, "BMC", &op_BMC);
            CGPDFOperatorTableSetCallback (pdfOpTable, "BDC", &op_BDC);
            CGPDFOperatorTableSetCallback (pdfOpTable, "EMC", &op_EMC);

            for(int i=0; i<pageCount; i++) {

                //set up
                CGPDFPageRef thisPage;
                CGPDFScannerRef pdfScanner;
                CGPDFContentStreamRef thisContentStream;

                //get the page
                thisPage = CGPDFDocumentGetPage (pdfDocument, i + 1 );

                //get the page content stream
                thisContentStream = CGPDFContentStreamCreateWithPage (thisPage);

                //create a pdf scanner using our previously created table and callbacks
                pdfScanner = CGPDFScannerCreate (thisContentStream, pdfOpTable, NULL);

                //scan the pdf file
                CGPDFScannerScan (pdfScanner); //-->call backs happen here

                //release everything
                CGPDFPageRelease (thisPage);
                /*CGPDFScannerRelease (pdfScanner);
                CGPDFContentStreamRelease (thisContentStream);*/


            }
        }
    }

    //release the pdf document
    CGPDFDocumentRelease(pdfDocument);


}

static void op_MP (CGPDFScannerRef s, void *info) {

    const char *name;

    if (!CGPDFScannerPopName(s, &name))
        return;

    NSLog(@"MP /%s\n", name);
}

static void op_DP (CGPDFScannerRef s, void *info) {
    const char *name;
    if (!CGPDFScannerPopName(s, &name))
        return;
    NSLog(@"DP /%s\n", name);
}

static void op_BMC (CGPDFScannerRef s, void *info) {
    const char *name;
    if (!CGPDFScannerPopName(s, &name))
        return;
    NSLog(@"BMC /%s\n", name);
}

static void op_BDC (CGPDFScannerRef s, void *info) {
    const char *name;
    if (!CGPDFScannerPopName(s, &name))
        return;
    NSLog(@"BDC /%s\n", name);
}

static void op_EMC (CGPDFScannerRef s, void *info) {
    const char *name;
    if (!CGPDFScannerPopName(s, &name))
        return;
    NSLog(@"EMC /%s\n", name);
}

编辑:PDFURL 来自此过程:用户选择使用应用程序打开附加到电子邮件的 PDF 文件。在 AppDelegate.m 中:

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
   /* NSLog(@"Open URL:\t%@\n"
          "From source:\t%@\n"
          "With annotation:%@",
          url, sourceApplication, annotation);*/

    NSMutableDictionary* userData = [[NSMutableDictionary alloc] init];

    [userData setObject:@"Read PDF" forKey:@"Action"];
    [userData setObject:url forKey:@"File Path"];

    [[NSNotificationCenter defaultCenter] postNotificationName:@"theMessenger" object:self userInfo: userData];

    //NSString *filepath = [url path];
    //...
    return YES;
}

在 viewcontroller.m 中

- (void) receiveNotification:(NSNotification* ) notification {
...
} else if ([strAction isEqualToString:@"Read PDF"]) {

            NSURL* documentURL = [[notification userInfo] objectForKey:@"File Path"];
            [self readPDFFile:documentURL];

        }
...

编辑:如果我不发布此页面应用程序仍然崩溃:

libobjc.A.dylib`objc_release: 0x3be89f20:cmp r0,#0 0x3be89f22:它当量 0x3be89f24: bxeq lr 0x3be89f26:ldr r1,[r0] 0x3be89f28: 移动 r2, #2 0x3be89f2a:ldr r1,[r1,#16] 0x3be89f2c: bfi r1, r2, #0, #2 0x3be89f30:ldrb r1,[r1] 0x3be89f32:tst.w r1,#2 0x3be89f36: bne 0x3be89f3e ; objc_release + 30 0x3be89f38: 移动 r1, #0 0x3be89f3a: b.w 0x3be981c0 ; -[NSObject 发布] 0x3be89f3e: movw r1, #19326 0x3be89f42:移动 r1,#507 0x3be89f46: 添加 r1, pc 0x3be89f48:ldr r1,[r1] 0x3be89f4a: b.w 0x3be875a0 ; objc_msg发送 0x3be89f4e: 无

【问题讨论】:

  • PDFURL 来自哪里?你确定它必须在你的方法中释放吗?
  • @Martin - 查看 OP 底部的编辑
  • 你不应该释放PDFURL,因为你在调用方法中不拥有documentURL
  • 这并没有什么不同。那么 NSURL 会通过 ARC 发布吗?当我在文档中时,我的问题就出现了。
  • 简化的规则是:如果你没有分配/创建/复制东西,就不要发布。这适用于 pageRef 和 url :)

标签: ios pdf


【解决方案1】:

不要发布这个页面。你通过 GET 调用而不是副本或创建方法获得它,这意味着你不拥有它

--

不要发布 PDURL.. 你从外面得到它,但你不拥有它

--

释放 operatorTable .. 你创建它

不要为多个扫描仪重复使用它

【讨论】:

  • 如果我将代码置于 i>0 条件下,它不会崩溃。但我也没有得到任何数据。
猜你喜欢
  • 1970-01-01
  • 2018-07-30
  • 1970-01-01
  • 1970-01-01
  • 2011-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-23
相关资源
最近更新 更多