How to get the image form URL passed by the share extension to the application

I am working on sharing an array of images from a gallery using a shared extension. I can get the image inside the sharing extension using

- (void)getImageFromExtension:(NSExtensionItem *)extensionItem { for(NSItemProvider *attachment in extensionItem.attachments) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ if([attachment hasItemConformingToTypeIdentifier:(NSString *)kUTTypeImage]) { [attachment loadItemForTypeIdentifier:(NSString *)kUTTypeImage options:nil completionHandler:^(id<NSSecureCoding> item, NSError *error) { NSURL *image = (NSURL *)item; if(error) { NSLog(@"Error retrieving image"); } else { dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"*** ### %@",[UIImage imageWithData:[NSData dataWithContentsOfURL:image]]); }); } }]; } }); } } 

What I really need, I need to pass the URL of the image to the container application. But could not get the image from this url. URL file:///var/mobile/Media/DCIM/101APPLE/IMG_1705.JPG format file:///var/mobile/Media/DCIM/101APPLE/IMG_1705.JPG

The data for this URL is always null. how to get image from this url?

+5
source share
1 answer

You are probably calling getImageFromExtension from didSelectPost . At the end of didSelectPost you should call completeRequestReturningItems:completionHandler: to tell the host application to complete the application extension request using an array of results. When this method is called, the entire ShareViewController is rejected and freed. When you call this at the end of didSelectPost , it starts before NSItemProvider can get the image URL. Because it happens asynchronously. To fix this, you should call completeRequestReturningItems:completionHandler: after NSItemProvider selected imageURL.

Here's how it should work:

 - (void)didSelectPost { NSString *typeIdentifier = (NSString *)kUTTypeImage NSExtensionItem *item = self.extensionContext.inputItems.firstObject; NSItemProvider *itemProvider = item.attachments.firstObject; if ([itemProvider hasItemConformingToTypeIdentifier:typeIdentifier]) { [itemProvider loadItemForTypeIdentifier:typeIdentifier options:nil completionHandler:^(NSURL *url, NSError *error) { NSURL *imageURL = (NSURL *)item self.saveImage(imageURL) [self.extensionContext completeRequestReturningItems:@[] completionHandler:nil]; }]; } } 

By the way, there is no need to use dispatch_async when working with NSItemProvider, since the provider is already performing its work asynchronously.

I wrote a blog post about this if you want to read a little more about it.

EDIT

Now you can upload the image using the path to the file you just extracted. This only works in extension! If you want to access the image from the containing application, you cannot use the file URL you just received. The sharing extension saves the selected image in a folder inaccessible to the contained application.

To make the image available to the containing application, you need to activate App Groups in your application and extension. Then the extension saves the image in a common container, and the containing application can receive it:

 func saveImage(url: NSURL) { guard let imageData = NSData(contentsOfURL: url) else { return } let selectedImage = UIImage(data: imageData) let fileManager = NSFileManager.defaultManager() if let sharedContainer = fileManager.containerURLForSecurityApplicationGroupIdentifier("YOUR_GROUP_IDENTIFIER") { if let dirPath = sharedContainer.path { let sharedImageFilePath = dirPath + "/image.png" let binaryImageData = UIImagePNGRepresentation(selectedImage!) binaryImageData?.writeToFile(sharedImageFilePath, atomically: true) // send the sharedImageFilePath to the containing app } } } 
+3
source

Source: https://habr.com/ru/post/1233836/


All Articles