NSItemProvider loadItem 方法 returns _NSItemProviderSandboxedResource 而不是 URL

NSItemProvider loadItem method returns _NSItemProviderSandboxedResource instead of URL

在我开发的其中一个应用程序中,我使用共享扩展来导入电子钱包通行证 (PKPass)。

在 iOS 13(包括最新的 beta 8)上,当从 iOS 邮件应用程序中调用共享扩展时,该扩展没有接收到预期格式的数据(URL).

这是分享扩展的 ShareViewController 的相关片段:

if let inputItems = self.extensionContext?.inputItems,
   let inputItem = inputItems.first as? NSExtensionItem,
   let attachments = inputItem.attachments,
   let attachment = attachments.first,
   attachment.hasItemConformingToTypeIdentifier("com.apple.pkpass" as String){
    attachment.loadItem(forTypeIdentifier: "com.apple.pkpass" as String, options: nil) { data, error in
        print ("data: \(String(describing: data))")
}

在 iOS 12(最新版本)上,这也适用于 iOS 邮件应用程序中的附件(除了例如文件应用程序中的文件);数据包含一个可选的 URL。 上面的打印语句在控制台显示如下:

data: Optional(file:///var/mobile/Library/Mail/8EF174CF-68B9-414E-A166-D04C9DBE020E/INBOX.imapmbox/Attachments/13846/2/Attachment-1.pkpass)

在 iOS 13(测试版 8)上,在 iOS 邮件应用程序中,数据包含一个可选的 _NSItemProviderSandboxedResource。 上面的打印语句在控制台显示如下:

data: Optional(<_NSItemProviderSandboxedResource: 0x2839aa9e0>)

这似乎只影响邮件应用程序。在文件应用程序中,数据如预期的那样保存 URL.

这是一个错误(实际上我已经在 beta 4 中使用反馈助手报告过这个问题)还是 iOS 13 引入的一些新的安全功能?在这种情况下,如何访问附件的 url/data?

我遇到了同样的错误,看来我现在找到了解决方案

尝试使用 attachments.last 而不是 .first

看起来像 Apple returns 多种邮件应用附件类型。

刚刚找到解决此问题的方法。

在iOS13之前调用

attachment.loadItem(forTypeIdentifier: "com.apple.pkpass" as String, options: nil) data, error in

数据也可以向下转换为 URL,如下所示

if let pkPassURL = data as? URL

如上述问题所述,在 iOS 13 中,这不再可能了。

相反,现在需要使用 "public.file-url" 作为类型标识符来调用 loadItem:

attachment.loadItem(forTypeIdentifier: "public.file-url" as String, options: nil) { (data, error) in

在 PKPass 项目的具体情况下,我在分享它们时注意到

  • 来自电子钱包应用的附件将仅符合 "com.apple.pkpass"
  • 来自例如邮件应用程序附件将同时符合 "com.apple.pkpass" 和 "public.file-url"

所以下面的代码可以用来处理这两种情况:

if let inputItems = self.extensionContext?.inputItems,
   let inputItem = inputItems.first as? NSExtensionItem,
   let attachments = inputItem.attachments,
   let attachment = attachments.first,
   attachment.hasItemConformingToTypeIdentifier("com.apple.pkpass" as String) {
    if attachment.hasItemConformingToTypeIdentifier("public.file-url" as String) {
        // extension is being called e.g. from Mail app
        attachment.loadItem(forTypeIdentifier: "public.file-url" as String, options: nil) { (data, error) in 
            if let sourcePKPassURL = data as? URL {
                //handle url here
            }
        }
    } else {
        // extension is being called from Wallet app
        attachment.loadItem(forTypeIdentifier: "com.apple.pkpass" as String, options: nil) { (data, error) in
            if let pkPassData = data as? Data,
               let pkPass = try? PKPass(data: pkPassData) {
               // handle pkPass here
            }
        }
    }
}

这适用于 iOS 12 和 iOS 13。

自 iOS13 以来,我在 Apple Mail 附件中遇到了同样的问题。另外,之前检查 UTI 并加载该类型在下面的代码中不起作用。

if let item = extensionContext?.inputItems.first as? NSExtensionItem {
        if let itemProvider = item.attachments?.first {
            let type = itemProvider.registeredTypeIdentifiers
            let uti = type.first!
            if itemProvider.hasItemConformingToTypeIdentifier(uti) {
                itemProvider.loadItem(forTypeIdentifier:uti, options: nil, completionHandler: { (item, error) -> Void in
                    print(item) //<_NSItemProviderSandboxedResource: 0x2839aa9e0>
                })
            }
        }}