Objective-C为PDF创建映射文件

时间:2018-03-01 18:02:00

标签: ios objective-c uidocumentinteraction nsurlsessiondatatask

我正在创建一个这样的文件:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString *documentsDirectory = [paths objectAtIndex:0];

filePath = [NSString stringWithFormat:@"%@/%@", documentsDirectory,PDFFile];

if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
     [[NSFileManager defaultManager] createFileAtPath:filePath contents:dataBytes attributes:nil];
}

_previewItemURL = [NSURL fileURLWithPath:filePath];

我将它显示在UIDocumentInteractionController中,如下所示:

if (_previewItemURL) {

    UIDocumentInteractionController *documentInteractionController =[UIDocumentInteractionController interactionControllerWithURL:_previewItemURL];
    documentInteractionController.delegate = self;

    [documentInteractionController presentPreviewAnimated:YES];
}

但是,有时我保存字节的PDF文件太大了,有时候是5.5MB,这会导致UIDocumentInteractionController在一段时间内加载PDF。我在这里做了一些阅读https://stackoverflow.com/a/27863508/979331,建议创建一个'映射'文件。我的问题是我不懂如何创建一个。我过去两天一直在疯狂地谷歌搜索,我只是不明白。

我认为问题出在PDF上,因为我试过这个:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *pgnPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.pdf", @"example"]];

    //filePath = [NSString stringWithFormat:@"%@/%@", documentsDirectory,PDFFile];

    //if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {

    NSString *newFile = [[NSBundle mainBundle] pathForResource:@"example" ofType:@"pdf"];

    [[NSFileManager defaultManager] copyItemAtPath:newFile toPath:pgnPath error:&error];

    //[[NSFileManager defaultManager] createFileAtPath:filePath contents:dataBytes attributes:nil];
//}

//_previewItemURL = [[NSBundle mainBundle] URLForResource:@"example" withExtension:@"pdf"];

_previewItemURL = [NSURL fileURLWithPath:pgnPath];

PDF为5.5MB,一切似乎都很好,问题可能在于我如何获取PDF?我从Web服务获取字节,这是我的电话:

task = [dataSource.areaData GetPDFFileTestTwo:[NSString stringWithFormat:@"%@",encodedUrlStr] completion:^(NSData *data, NSURLResponse *response, NSError *error) {

    NSError *myError;
    NSArray *tableArray = [[NSArray alloc]initWithArray:[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&myError]];

    NSData *dataBytes;

    for (NSDictionary *dict in tableArray) {
        NSString *base64 = dict[@"data"];
        dataBytes = [[NSData alloc] initWithBase64EncodedString:base64 options:0];
    }

    if (dataBytes) {

        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];

        filePath = [NSString stringWithFormat:@"%@/%@", documentsDirectory,PDFFile];

        if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
            [[NSFileManager defaultManager] createFileAtPath:filePath contents:dataBytes attributes:nil];
        }

        _previewItemURL = [NSURL fileURLWithPath:filePath];

        if (_previewItemURL) {

            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

            UIDocumentInteractionController *documentInteractionController =[UIDocumentInteractionController interactionControllerWithURL:_previewItemURL];

            documentInteractionController.delegate = self;

            dispatch_async(dispatch_get_main_queue(), ^{

            [documentInteractionController presentPreviewAnimated:YES];

        });


    });
}


            }

        }];

这是GetPDFFileTestTwo

-(NSURLSessionDataTask *)GetPDFFileTestTwo:(NSString *)PDFFile completion:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler{

    NSString *FileBrowserRequestString = [NSString stringWithFormat:@"%@?PDFFile=%@",kIP,PDFFile];
    NSURL *JSONURL = [NSURL URLWithString:FileBrowserRequestString];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:JSONURL];
    NSURLSession *session = [NSURLSession sharedSession];

    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){

        if(completionHandler)
        {
            completionHandler(data, response, error);
        }

    }];

    [dataTask resume];

    return dataTask;

}

kIP是一个字符串,它是Web服务URL

2 个答案:

答案 0 :(得分:1)

您没有“创建”映射文件。你将它读入NSData映射到文件中的字节。这意味着,内存中的NSData字节在下面映射到文件中的字节。

这是一种将文件读取为映射的方法:

https://github.com/atomicbird/atomictools/blob/master/NSData%2BreallyMapped.h

如果您无法将NSData传递给控制器​​进行预览,则映射毫无意义。即使可以,也必须确保控制器在使用之前不会复制数据。

考虑使用PDFKit框架,您可以使用PDFDocument初始化NSData并在PDFView中显示。

答案 1 :(得分:0)

你的问题;

  
      
  1. 创建'已映射'文件。我的问题是我不明白怎么做   创造一个。
  2.   

因此,我要指出UIDocumentInteractionController没有接受NSData的输入,因此您将无法创建与其一起使用的内存映射文件。我还检查了任何其他线索的标题,但没有找到任何线索。 https://developer.apple.com/documentation/uikit/uidocumentinteractioncontroller

在寻找解决方案时,我看到QLPreviewController提到“数据”,但我发现它也不接受NSData。 https://developer.apple.com/documentation/quicklook/qlpreviewcontroller

我最终决定使用WebKit中的WKWebView,它支持使用NSData,即内存映射,并且使用15 MB的PDF完整加载我的图片和文本。

我创建了一个包含大型PDF的项目并试用了它,它运行正常。请随意检查。 https://github.com/eSpecialized/PDFDocViewerMapped

“已映射”的工作原理;

任何可以采用NSData的东西都可以使用映射文件,除非它一次需要整个数据集。具有单个图像与多页PDF的PDF是无法映射的内容和可以映射的内容的良好示例。

    NSError *errors;
    NSData *docFileData = [NSData dataWithContentsOfFile:docFileWithPath options:NSDataReadingMappedAlways error:&errors];

NSData的选项映射;

https://developer.apple.com/documentation/foundation/nsdatareadingoptions?language=objc

NSDataReadingMappedIfSafe // Hint to map the file in if possible and safe
NSDataReadingMappedAlways // Hint to map the file in if possible. This takes precedence over NSDataReadingMappedIfSafe if both are given.
  
      
  1. 问题可能与我如何获取PDF有关吗?
  2.   

远程获取PDF意味着您必须下载文档。   想想你正在做什么,获取Pdf,在本地保存它,然后在UIDocument Interaction控制器中打开它,该控制器采用URL而不是NSData。

我希望这符合您的解决方案标准;

  • UIDocumentInteractionController限制需要URL

  • WKWebView - 允许使用可以进行内存映射的NSData。

  • PDF查看的第三方选项 - 任何可以接受NSData的选项都是 候选人使用。寻找CocoaPods,在GitHub上寻找PDF,iOS PDF, 等