iOS8: UIDocumentPickerViewController get NSData

邮差的信 提交于 2020-01-02 06:58:35

问题


I have implement UIDocumentPickerViewController according docs and now trying to get NSData from picked file in delegate method, but [[NSData alloc] initWithContentsOfURL:] returns nil:

- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentAtURL:(NSURL *)url{
    NSData* documentData = [[NSData alloc] initWithContentsOfURL:url];
    //documentData is nil
    documentData = [[NSData alloc] initWithContentsOfFile:[url path]];
    //documentData is still nil :(
}

I'm using Xcode6 beta6, iPhone simulator, document picker mode is UIDocumentPickerModeImport. Trying to retrieve documents saved to iCloude Drive.


回答1:


Elaborating on @cescofry's answer a bit here regarding iWork files (.pages, .numbers, .key) so others won't have to rediscover the issue. (This will work for non iWork files as well.)

If you are pulling iWork files from iCloud, you need to worry about two primary things before you can get a valid NSData object. A) Security scope through a NSFileCoordinator object (as covered by @cescofry) and B) that iWork files are actually directories/bundles not single files. The options parameter you want for coordinateReadingItemAtURL: is NSFileCoordinatorReadingForUploading. This will read in single files as if you had used 0, but will turn directories into zip files automatically. Strip off the .zip that is added on and you'll have a valid Pages/Numbers/Keynote file. (It's valid with it on too.)

[url startAccessingSecurityScopedResource];
NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] init];
NSError *error;
__block NSData *fileData;

[coordinator coordinateReadingItemAtURL:url options:NSFileCoordinatorReadingForUploading error:&error byAccessor:^(NSURL *newURL) {
   // File name for use in writing the file out later
   NSString *fileName = [newURL lastPathComponent];
   NSString *fileExtension = [newURL pathExtension];

   if([fileExtension isEqualToString:@"zip"]) {
     if([[[newURL URLByDeletingPathExtension] pathExtension] isEqualToString:@"pages"] ||
        [[[newURL URLByDeletingPathExtension] pathExtension] isEqualToString:@"numbers"] ||
        [[[newURL URLByDeletingPathExtension] pathExtension] isEqualToString:@"key"] ) {
       // Remove .zip if it is an iWork file
       fileExtension = [[newURL URLByDeletingPathExtension] pathExtension];
       fileName = [[newURL URLByDeletingPathExtension] lastPathComponent];
     }
   }

   NSError *fileConversionError;
   fileData = [NSData dataWithContentsOfURL:newURL options:NSDataReadingUncached error:&fileConversionError];

   // Do something with the file data here

}
[url stopAccessingSecurityScopedResource];

Relevant Apple documentation on the NSFileCoordinator options here: https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSFileCoordinator_class/#//apple_ref/c/tdef/NSFileCoordinatorReadingOptions




回答2:


A URL from a document picker needs to be accessed through a file coordinator. Further more the url needs to be looked in scope:

[url startAccessingSecurityScopedResource];

__block NSData *data

 NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] init];
 NSError *error;
 [coordinator coordinateReadingItemAtURL:url options:0 error:&error byAccessor:^(NSURL *newURL) {
    data = [NSData dataWithContentsOfURL:url];
 }];

 [url stopAccessingSecurityScopedResource];

More from the Apple documentation




回答3:


The problem was that actually Page documents (*.pages) are not files, but folders. So when I have tried to get NSData from folders path it returns nil.

Default Mail.app attaches documents as zip archives.



来源:https://stackoverflow.com/questions/25520453/ios8-uidocumentpickerviewcontroller-get-nsdata

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!