如何在 iOS 上共享就地打开文件

How to share files for open-in-place on iOS

我们有一个 iOS 应用程序通过 Core Data 管理文档。实际文件驻留在应用程序的共享容器中,以便应用程序的文件提供程序扩展也可以访问它们以获得 Files.app 支持。我们希望为用户提供在第三方应用程序中打开这些文件的选项,以便他们可以就地编辑它们,而不是将副本发送到其他应用程序。

我们提供 UIActivityViewController 用于与其他应用共享文件。我们还提供了一个 UIActivity 来显示 UIDocumentInteractionController 在某些情况下似乎效果更好。我们给 UIActivityViewController 文档的文件 URL、原始文本内容和可打印数据。

这有效,但所有第三方编辑器都显示为复制到……而不是打开于……

我们还在应用的 info.plist 中将 UIFileSharingEnabledLSSupportsOpeningDocumentsInPlace 属性设置为 YES,但它们似乎只与就地打开有关共享位于应用 Documents 文件夹中的文件时。

现在我们偶然发现了 NSItemProviderNSItemProviderFileOptionOpenInPlace 选项。由于我们已经支持文件提供程序扩展,并且从 Apple 的文档来看,这似乎是完成我们想要的事情的好地方。

添加 "pure" NSItemProvider 在某种程度上是有效的,但显示的选项少于同时共享文件 URL 和另外的文本(这是预期的)。但是,当我们将 -[NSItemProvider registerFileRepresentationForTypeIdentifier:fileOptions:visibility:loadHandler:] 与上述选项(或仅零,结果相同)和 return 一起使用时,loadHandlercompletionHandler() 中的文件 URL 什么都没有已共享。例如,Mail 不再附加文件,Messages 不显示要发送的文档。

这些是代码的相关位:

NSMutableArray *items = [NSMutableArray array];
NSMutableArray <UIActivity *> *activities = [NSMutableArray array];

NSURL *fileURL = self.record.metadata.fileURL;
NSString *fileUTI = self.record.metadata.uti;
NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithItem: fileURL typeIdentifier: fileUTI];
[itemProvider registerFileRepresentationForTypeIdentifier:fileUTI fileOptions:NSItemProviderFileOptionOpenInPlace visibility:YES loadHandler:^NSProgress * _Nullable(void (^ _Nonnull completionHandler)(NSURL * _Nullable, BOOL, NSError * _Nullable))
{
    if (fileURL)
        completionHandler(fileURL, YES, nil);
    else
        completionHandler(nil, YES, [NSError errorWithDomain:NSCocoaErrorDomain code:NSURLErrorFileDoesNotExist userInfo:nil]);
    return nil;
}];
[items addObject:itemProvider];

self.activityViewController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:activities];
[UIAppDelegate.splitViewController presentViewController:self.activityViewController animated:YES completion:nil];

使用共享菜单正确调用项目提供程序的加载处理程序和文件的实际 URL returned。

这不是 NSItemProviderFileOptionOpenInPlace 的用途吗?或者我们只是错误地使用它? Apple 的描述非常稀疏,除了官方文档外,我们在互联网上找不到任何其他信息。

我发现了我的问题所在:对 activity 视图控制器和文件提供程序之间的关系理解不够深入。

由于我的所有文件都驻留在共享容器中并且也通过文件提供程序扩展发布,因此我需要通过 activity 视图控制器共享的内容与共享的 URL 完全相同通过文件提供者扩展。从技术上讲,打开文件的应用程序通过文件提供程序机制访问它。