CGPDFDictionaryRef для чего-то полезного - PullRequest
7 голосов
/ 11 августа 2010

Немного фона: я добавляю изображение в уже существующий PDF-файл.Я обнаружил, что нет способа просто добавить страницу на него, вы должны воссоздать весь PDF, затем удалить старую и переместить новую.(Если это не так , пожалуйста, , скажите мне, и это избавит меня от многих головных болей.) Я выполнил эту часть, но сейчас пытаюсь скопировать вспомогательную информацию (название, автор,Ключи и т. Д.).Проблема в том, что существует так много проблем с типами, что текущий метод, который я использую, заключается в том, чтобы получить CGPDFDictionaryRef в CGPDFDocumentRef, а затем вызвать CGPDFDictionaryApplierFunction.В функции C, которую я передаю, я извлекаю каждый ключ в NSMutableDictionary, чтобы затем я мог что-то делать со значениями и не блокировать их в этом ужасном формате CGPDF.

Так что в основном мой вопрос будет следующим:Есть ли лучший способ сделать это?Я смотрел на очень много файлов документации, я не мог себе представить, что ничего не пропустил, но действительно надеюсь, что у меня есть, потому что количество обходного пути, которое я должен сделать, становится абсурдным.

Ответы [ 2 ]

11 голосов
/ 11 августа 2010

Я закончил мой обходной путь. Я все еще хотел бы знать, есть ли лучший способ сделать это, поэтому, если вы знаете один из них или у вас есть какие-либо предложения, я готов их опробовать.

Примечания. Я проверяю только значения bool, ints, string и arrays, потому что согласно документации Apple это все, что должно быть в дополнительной информации в PDF. Бит массива не проверен, потому что у меня нет PDF с массивом в Aux Info. Если кто-то захочет проверить это для меня или ссылку на PDF-файл с одним из них, я с удовольствием проверим это.

Сначала в заголовке класса создайте id selfClass вне тегов @interface, чтобы функции C, вызываемые CGPDFDictionaryApplyFunction, могли получить доступ к текущему классу. Также добавьте NSDictionary *auxInfo для хранения информации. После извлечения тип NS можно легко разыграть следующим образом:

CFDictionaryRef newDictionary = (CFDictionaryRef)[self auxInfo];

Я фактически закончил прошлой ночью, но подумал, что мне нужно сделать еще один цикл зацикливания, чтобы перейти от NS к CF, забыв, что они были соединены без токенов. Итак, у вас есть это, надеюсь, что все получат пользу от моих трудов. Задавайте вопросы, если вам нужны разъяснения. И еще раз, если есть более простой способ сделать это, если только оптимизация моего кода, скажите, пожалуйста. Я знаю, что это не очень элегантный способ сделать это, но пока он работает.

- (void)extractPDFDictionary:(CGPDFDocumentRef)pdf{
    NSLog(@"extractingPDFDictionary");
    CGPDFDictionaryRef oldDict = CGPDFDocumentGetInfo(pdf);
    CGPDFDictionaryApplyFunction(oldDict, copyDictionaryValues, NULL);
}

void copyDictionaryValues (const char *key, CGPDFObjectRef object, void *info) {
    NSLog(@"key: %s", key);
    CGPDFObjectType type = CGPDFObjectGetType(object);
    switch (type) {
        case kCGPDFObjectTypeString: {
            CGPDFStringRef objectString;
            if (CGPDFObjectGetValue(object, kCGPDFObjectTypeString, &objectString)) {
                NSString *tempStr = (NSString *)CGPDFStringCopyTextString(objectString);
                [[selfClass auxInfo] setObject:tempStr
                                         forKey:[NSString stringWithCString:key encoding:NSUTF8StringEncoding]];
                [tempStr release];
                NSLog(@"set string value");
            }
        }
        case kCGPDFObjectTypeInteger: {
            CGPDFInteger objectInteger;
            if (CGPDFObjectGetValue(object, kCGPDFObjectTypeInteger, &objectInteger)) {
                [[selfClass auxInfo] setObject:[NSNumber numberWithInt:objectInteger]
                                         forKey:[NSString stringWithCString:key encoding:NSUTF8StringEncoding]];
                NSLog(@"set int value");
            }
        }
        case kCGPDFObjectTypeBoolean: {
            CGPDFBoolean objectBool;
            if (CGPDFObjectGetValue(object, kCGPDFObjectTypeBoolean, &objectBool)) {
                [[selfClass auxInfo] setObject:[NSNumber numberWithBool:objectBool]
                                         forKey:[NSString stringWithCString:key encoding:NSUTF8StringEncoding]];
                NSLog(@"set boolean value");
            }
        }
        case kCGPDFObjectTypeArray : {
            CGPDFArrayRef objectArray;
            if (CGPDFObjectGetValue(object, kCGPDFObjectTypeArray, &objectArray)) {
                NSArray *tempArr = [selfClass copyPDFArray:objectArray];
                [[selfClass auxInfo] setObject:tempArr
                                         forKey:[NSString stringWithCString:key encoding:NSUTF8StringEncoding]];
                [tempArr release];
                NSLog(@"set array value");
            }
        }

    }
}

- (NSArray *)copyPDFArray:(CGPDFArrayRef)arr{
    int i = 0;
    NSMutableArray *temp = [[NSMutableArray alloc] init];
    for(i=0; i<CGPDFArrayGetCount(arr); i++){
        CGPDFObjectRef object;
        CGPDFArrayGetObject(arr, i, &object);
        CGPDFObjectType type = CGPDFObjectGetType(object);
        switch(type){
            case kCGPDFObjectTypeString: {
                CGPDFStringRef objectString;
                if (CGPDFObjectGetValue(object, kCGPDFObjectTypeString, &objectString)) {
                    NSString *tempStr = (NSString *)CGPDFStringCopyTextString(objectString);
                    [temp addObject:tempStr];
                    [tempStr release];
                }
            }
            case kCGPDFObjectTypeInteger: {
                CGPDFInteger objectInteger;
                if (CGPDFObjectGetValue(object, kCGPDFObjectTypeInteger, &objectInteger)) {
                    [temp addObject:[NSNumber numberWithInt:objectInteger]];
                }
            }
            case kCGPDFObjectTypeBoolean: {
                CGPDFBoolean objectBool;
                if (CGPDFObjectGetValue(object, kCGPDFObjectTypeBoolean, &objectBool)) {
                    [temp addObject:[NSNumber numberWithBool:objectBool]];
                }
            }
            case kCGPDFObjectTypeArray : {
                CGPDFArrayRef objectArray;
                if (CGPDFObjectGetValue(object, kCGPDFObjectTypeArray, &objectArray)) {
                    NSArray *tempArr = [selfClass copyPDFArray:objectArray];
                    [temp addObject:tempArr];
                    [tempArr release];
                }
            }
        }
    }
    return temp;
}
0 голосов
/ 11 августа 2010

Вы можете выполнить то, что описываете, нарисовав CGPDFContext, но если у вас сложный PDF, вы можете попытаться сделать что-то помимо того, для чего предназначен API.Вы можете взглянуть на раздел 3.4 спецификации PDF и посмотреть, что вы получаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...