How to fetch screenshot in iOS Share Extension?

Viewed 623

I have created a share extension for my app through which users will be able to create a post with images. It works perfectly well when any image from "Photos" is selected and shared but when a screenshot is taken and directly shared, the share extension is not able to fetch it.

I have written the code that is used to fetch images.

-(void)fetchImages {
    for (NSExtensionItem *item in self.extensionContext.inputItems) {

        [item.attachments enumerateObjectsUsingBlock:^(NSItemProvider * _Nonnull itemProvider, NSUInteger idx, BOOL * _Nonnull stop) {
            if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeImage]) {
                [itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeImage options:nil completionHandler:^(NSData *image, NSError *error) {
                    // You will get Image data here that you can submit to server.
                    [self showAlertWithMessage:[error localizedDescription]];

                    if(image) {
                        [self saveImage:image atIndex:idx];
                    }
                }];
            }
        }];
    }
}

The above method is called after viewDidLoad. When any image is selected from "Photos" it is displayed perfectly well but when a screenshot is shared immediately after being taken, I get the error "could not coerce an item to class nsdata". Any help on this would me much appreciated. Thanks.

2 Answers

Although this question was asked long before but I was facing the same issue. In share extension I was able to fetch images/files/audios/vides when selected photos/files but when I was trying to share screenshot instantly after capturing that I was unable to retrieve screenshot data as NSData but it wasn't in correct format and was unable to show that. After hours of effort I found the solution, You need to check two things:

Explanation of problem: 1- when screenshot is taken it's not of type kUTTypeImage instead it's of type public.image. So while fetching data of type keep this thing in mind. 2- Secondly you can't fetch it as NSData you need to fetch it as 'id item' in completion handler.

Example:

// To extract selected files
NSExtensionItem *selectedContent = self.extensionContext.inputItems[0];
// For single selected files, selected content will be at 0 index
NSItemProvider *itemProvider = extensionItem.attachments[0]; // No need to worry about multiple selected files, you can iterate extensionItem.attachments to extract all selected files one by one.
// Now extract all registered **itemTypeIdentifiers** instead of fetching data by providing type by yourself
NSArray *registeredTypeIdentifiers = itemProvider.registeredTypeIdentifiers;
// You can validate before fetching that actually the selected item is of corresponding type
if ([itemProvider hasItemConformingToTypeIdentifier:registeredTypeIdentifiers.firstObject]) {
           // Now fetch data by passing corresponding data type      
          [itemProvider loadItemForTypeIdentifier:registeredTypeIdentifiers.firstObject options:nil completionHandler:^(id<NSSecureCoding> item, NSError *error) {
              if (item) {
                        
                  // For all selected photos/files
                  if([(NSObject*)item isKindOfClass:[NSURL class]]) {
                      NSData *contentData = [NSData dataWithContentsOfURL:(NSURL *)item];
                    // continue working with selected image/file
                  }
                  if([(NSObject*)item isKindOfClass:[UIImage class]]) {
                     NSData  *contentData = UIImagePNGRepresentation((UIImage*)item);
                    // continue working with screenshot data
                  }
                        
              }
          }];
                
}

cheers!

- (void)loadItemForTypeIdentifier:(NSString *)typeIdentifier options:(nullable NSDictionary *)options completionHandler:(nullable NSItemProviderCompletionHandler)completionHandler;

typedef void (^NSItemProviderCompletionHandler)(__nullable id <NSSecureCoding> item, NSError * __null_unspecified error);

item may be of multiple types。

Related