NSItemProvider loadItem method returns _NSItemProviderSandboxedResource instead of URL
Just found a solution for this issue.
Prior to iOS 13 when calling
attachment.loadItem(forTypeIdentifier: "com.apple.pkpass" as String, options: nil) data, error in
data could be downcasted also to an URL as follows
if let pkPassURL = data as? URL
As described in the question above, in iOS 13 this is not possible any longer.
Instead, it is now required to call loadItem with "public.file-url" as type identifier:
attachment.loadItem(forTypeIdentifier: "public.file-url" as String, options: nil) { (data, error) in
In the specific case of PKPass items, I have noticed that when sharing them
- from the Wallet app the attachment will conform only to "com.apple.pkpass"
- from e.g. Mail app the attachment will conform to both "com.apple.pkpass" and "public.file-url"
So following code can be used to deal with both cases:
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
}
}
}
}
This works for both iOS 12 and iOS 13.