3

I am sure this is trivial once someone kindly point me in the right direction so my apology for asking a silly question. However I have been searching for days I can't figure out what I am doing wrong.

Scenario: create a simple share extension that receives an image file

Problem: when I access the attachements, the handler is never called albeit I can see the "public.jpg" in the itemProvider but I can't see where the data would be?

What I have done:

1) defined NSExtensionActivationSupportsImageWithMaxCount = 1 as my only activation rule
2) added CoreMedia framework to the extension
3) added the same group to both app and app extension
4) made sure both have the group (1) in the entitlement
5) made sure both are using a certificate/app id with that group enabled
6) clean and rebuild several times to no avail.

The code:

- (void)didSelectPost {
/
for (NSExtensionItem *item in self.extensionContext.inputItems) {
    for (NSItemProvider *itemProvider in item.attachments) {
        if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeImage]) {
I can hit this breakpoint --> [itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeImage options:nil completionHandler:^(UIImage *image, NSError *error) {
but not this one --> photo = image;
            }];
            break;
        }
    }
}
.... and so on and so forth
Rene Pot
  • 24,681
  • 7
  • 68
  • 92
  • As you have indicated the answer below is correct, you should mark it as correct. I believe you may even get some SO points as well. – eric Jan 18 '16 at 20:18

1 Answers1

6

You haven't posted your complete code but I suspect that you are calling completeRequestReturningItems:completionHandler: at the wrong location:

WRONG:

- (void)didSelectPost {
        NSExtensionItem *item = self.extensionContext.inputItems.firstObject;
        NSItemProvider *itemProvider = item.attachments.firstObject;
        if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeImage]) {
            [itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeImage
                                            options:nil
                                  completionHandler:^(NSURL *url, NSError *error) {
                                      // send the image
                                  }];
        }
        // ↓ this is the wrong location ↓
        [self.extensionContext completeRequestReturningItems:@[] completionHandler:nil];
    }

The problem is that calling completeRequestReturningItems:completionHandler: immediately dismisses the ShareViewController and deallocates it. So the NSItemProvider that contains the image is also destroyed before it can access the image (because it loads its items asynchronously). In other words: the completion handler in which you send the image to your server is never called, because the whole shareViewController has already been deallocated.

To fix that problem you have to move the call to completeRequestReturningItems:completionHandler: to the end of the completion handler AFTER you send the image.

CORRECT:

- (void)didSelectPost {
    NSExtensionItem *item = self.extensionContext.inputItems.firstObject;
    NSItemProvider *itemProvider = item.attachments.firstObject;
    if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeImage]) {
        [itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeImage
                                        options:nil
                              completionHandler:^(NSURL *url, NSError *error) {
                                  // send the image
                                  [self.extensionContext completeRequestReturningItems:@[]         
                                                                     completionHandler:nil];
                              }];
    }
}
joern
  • 27,354
  • 7
  • 90
  • 105
  • You are absolutely right. I got a similar hint form the Apple developer forum. Thank you! For anybody else reading this, just follow Rene directions and make sure you do no send the complete request message until you get the data. – Andrea Mariotti Oct 09 '15 at 03:01
  • Glad that it helped you. Please mark the answer as accepted so others can see that it solved your problem. – joern Oct 09 '15 at 05:11
  • Thanks joern. While this doesn't help my problem, I appreciate the details you supplied the asker. – eric Jan 18 '16 at 20:18
  • Thanks! This helped a lot! I shouldn't have called completeRequestReturningItems at the end of didSelectPost, only inside of the completion handler. – EternalLight Nov 06 '17 at 08:12
  • the problem is [itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeImage can not returen an image despite completeRequestReturningItems has put the right location. – evan Jun 17 '20 at 05:10
  • one more thing: I have test my code. if you have set the completeRequestReturningItems location right. the image will return. so the completeRequestReturningItems must right as @joern said. – evan Jun 18 '20 at 09:38