获取CGPDFDocumentRef文档名称

时间:2011-05-04 10:23:16

标签: ios cgpdfdocument

是否可以从CGPDFDocumentRef

中检索文档的名称

2 个答案:

答案 0 :(得分:5)

通过“文档名称”,您的意思是文档文件名或标题吗?

如果文档“title”包含在元数据中,则可以像这样检索它:

    char *titleKey = "Title";
    CGPDFStringRef titleStringRef;

    CGPDFDictionaryRef info = CGPDFDocumentGetInfo(myDocumentRef);
    CGPDFDictionaryGetString(info, titleKey, &titleStringRef);
    const unsigned char *titleCstring = CGPDFStringGetBytePtr(titleStringRef);

    printf("title: %s", titleCstring);

其他密钥在PDF 1.7规范的第10.2节中列出:Adobe PDF Reference Archives

答案 1 :(得分:1)

这是在Swift 5中执行此操作的方法:

extension CGPDFDocument {
    var title: String? {
        guard let infoDict = self.info else {
            return nil
        }
        let titleKey = ("Title" as NSString).cString(using: String.Encoding.ascii.rawValue)!
        var titleStringRef: CGPDFStringRef?
        CGPDFDictionaryGetString(infoDict, titleKey, &titleStringRef)
        if let stringRef = titleStringRef,
           let cTitle = CGPDFStringGetBytePtr(stringRef) {
            let length = CGPDFStringGetLength(stringRef)
            let encoding = CFStringBuiltInEncodings.UTF8.rawValue
            let allocator = kCFAllocatorDefault
            let optionalTitle: UnsafePointer<UInt8>! = Optional<UnsafePointer<UInt8>>(cTitle)
            if let title = CFStringCreateWithBytes(allocator, optionalTitle, length, encoding, true) {
                return title as String
            }
        }
        return nil
    }
}

这是我对其工作方式的理解:

首先,我们检查PDF文档是否附有信息字典。 PDF信息字典可以包含包含文档标题的元数据。*

        guard let infoDict = self.info else {
            return nil
        }

如果确实如此,我们尝试使用CGPDFDictionary API从该词典中获取标题。该API仅接受C类型,因此我们需要执行一些转换才能将Swift String ”Title”表示为C字符串。

        let titleKey = ("Title" as NSString).cString(using: String.Encoding.ascii.rawValue)!

CGPDFDictionaryGetString调用将指向CGPDFStringRef?变量的指针作为其第三个参数。要将Swift引用转换为指针,我们在其前面加上&。如果在创建PDF时未指定标题,则字典查找的结果可能为nil。

        var titleStringRef: CGPDFStringRef?
        CGPDFDictionaryGetString(infoDict, titleKey, &titleStringRef)
        if let stringRef = titleStringRef,
           let cTitle = CGPDFStringGetBytePtr(stringRef) {

至此,我们知道有一个标题字符串,但是尚不在可用的Swift字符串中。要从内存中读取C字符串(使用CFStringCreateWithBytes),我们需要知道它的起始位置(指针)以及停止读取多少字节后的长度(长度)。此外,我们指定应使用UTF-8编码读取字符串,并使用默认的内存布局。我们需要的最后一项是对C字符串的正确键入引用。 C字符串的类型是指向char的指针,该指针在内存中表示为UInt8。所以我们以Optional<UnsafePointer<UInt8>>结尾。

            let length = CGPDFStringGetLength(stringRef)
            let encoding = CFStringBuiltInEncodings.UTF8.rawValue
            let allocator = kCFAllocatorDefault
            let optionalTitle: UnsafePointer<UInt8>! = Optional<UnsafePointer<UInt8>>(cTitle)

收集到这些信息后,现在该从C字符串中获取Swift字符串了。值得庆幸的是,CFString是免费的桥接到Swift的String,这意味着我们可以使用CFStringCreateWithBytes调用并将结果简单地转换为String。

            if let title = CFStringCreateWithBytes(allocator, optionalTitle, length, encoding, true) {
                return title as String
            }
        }
        return nil

*此字典中各个值的键可在第Adobe PDF Reference book,表8.4的表10.2“文档信息字典中的条目”中找到。