通过共享扩展从图库中保存照片时 NSData WriteToFile 失败

Posted

技术标签:

【中文标题】通过共享扩展从图库中保存照片时 NSData WriteToFile 失败【英文标题】:NSData WriteToFile Fails while saving a photo from gallery through Share Extension 【发布时间】:2016-03-30 11:15:09 【问题描述】:

我正在编写一个具有共享扩展名的应用程序,以将所选照片从 iphone 照片库保存到我的应用程序的本地存储中。 NSData WriteToFile 返回 YES,但我无法在写入时提供路径的目录中找到存储的文件。 因此,简而言之,NSData WriteToFile 无法在给定路径保存照片。

下面是我的代码。

   - (IBAction)acceptButtonTapped:(id)sender

    __block UIImage *photo;
    for (NSExtensionItem *item in self.extensionContext.inputItems)
    
        for (NSItemProvider *itemProvider in item.attachments)
        
            if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeImage])
            
                [itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeImage options:nil completionHandler:^(UIImage *image, NSError *error) 
                    if(image)
                    
                        dispatch_async(dispatch_get_main_queue(), ^
                            photo = image;

                            NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

                            [formatter setDateFormat:@"yyyy_MM_dd_hh_mm_ss"];

                            NSString *fileName;

                            fileName = [NSString stringWithFormat:@"%@.jpeg",[formatter stringFromDate:[NSDate date]]];

                            dataPath = [dataPath stringByAppendingPathComponent:fileName];
                            NSData * imageData = [NSData dataWithData:UIImageJPEGRepresentation(image, 1.0)];
                            BOOL isdone = [imageData writeToFile:dataPath atomically:NO];
                            NSLog(@"%u", isdone);
                        );
                    
                ];
                break;
            
        
    

    [self.extensionContext completeRequestReturningItems:@[] completionHandler:nil];

任何帮助都会非常重要。

谢谢。

【问题讨论】:

请验证“dataPath”,即它是否包含像 DocumentDirectory 这样的本地存储路径? 它在 DocumentDirectory 中,我在 DocumentDirectory 中创建了一个文件夹,并在其中存储了照片。这有什么问题吗? 将路径记录到模拟器上的调试控制台,然后将除文件名之外的所有内容复制到剪贴板,转到查找器,按命令 shift G,然后将路径粘贴到“转到文件夹”中对话框。走着瞧吧。还要在applicationDidFinishLaunching 中记录文档目录的路径,并确保您的路径指向该目录中的文件。 【参考方案1】:

如果您尝试从共享扩展程序访问文档目录,您不能这样做。共享扩展或其他小部件是与其包含的应用程序分开的应用程序,因此有自己的沙箱。因此,您将需要使用 App Groups 来共享文件。

应用程序组主要针对扩展,更具体地说,针对小部件。

NSFileManager 上面有一个方法containerURLForSecurityApplicationGroupIdentifier:您可以在其中传入您在为您的应用打开应用组时创建的标识符

NSURL *containerURL = [[NSFileManager defaultManager] 
           containerURLForSecurityApplicationGroupIdentifier:@"group.com.company.app"];

您可以将文件保存到此位置,因为您可以从扩展程序和主机应用程序访问共享的应用程序组。

【讨论】:

是的,您对容器 URL 的看法是正确的,但是当我在该 url 存储任何文件时,它每次都会失败。我需要创建任何目录然后尝试存储吗?它告诉我没有这样的文件或目录的错误 您必须在项目功能选项卡中创建应用组,该组必须对小部件和主机应用程序都是通用的。并更改上述代码中创建的应用组标识符名称。那么它应该可以工作了。【参考方案2】:

您在每次通过循环时都在修改 dataPath,并为其附加另一个文件名。这将创建一系列包含所有文件名的格式错误的路径。

不要那样做。创建一个新的局部变量fi​​lePath,并使用

将文件名构造成filePath
filePath = [docsPath stringByAppendingPathComponent: filename];

记录您的路径并看看它。当您的程序未按预期运行时,请不要相信您的任何假设,因为其中一个或多个可能是错误的。

【讨论】:

以上是关于通过共享扩展从图库中保存照片时 NSData WriteToFile 失败的主要内容,如果未能解决你的问题,请参考以下文章

在Flutter中保存照片(尤其是相机胶卷)

IOS:从照片路径获取 NSData

从照片库保存照片

OpenCV:在 IYUV 中保存视频

如何在 TabView SwiftUI 中保存视图的列表状态

在导航抽屉片段中保存视图页面片段的状态