Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Share extensions will *only* show up if they explicitly support *all* of the provided activity items #5

Closed
irace opened this issue Sep 15, 2014 · 10 comments

Comments

@irace
Copy link
Contributor

irace commented Sep 15, 2014

This is a doozy. It’s the most important issue we’ve found, and one that probably deserves a blog post of its own.

Here’s how applications pass data to share extensions:

  • An application configures a UIActivityViewController with an array of “activity items”
  • The activity controller displays the system activities and share extensions that can operate on the types of items provided

Here’s how we think this should work, using the Tumblr app as an example:

  • The user long-presses on a photo
  • We put the image data, the posts’s URL, and maybe a text summary of the post, all in the activity items array
  • We’d expect share extensions that support either image data or URLs or text to all show up in the activity controller

What actually happens is that only share extensions that explicitly support images and URLs and text will show up.

This is a problem, because the simplest way to specify what your extension supports – and by far the best documented – is by adding NSExtensionActivationRule keys like:

`NSExtensionActivationSupportsText` : `YES`

This looks like it would mean “show my extension as long as any of the activity items are text,” but it really means “show my extension as long as there is only one activity item, and it is text.”

Federico Viticci, who at this point has likely used more third-party share extensions than anyone else on the planet, verifies that this is in fact a legitimate problem:

@irace Yup. Been talking to devs to handle exceptions when possible, but I'm getting a lot of failures in several apps.

— Federico Viticci (@viticci) September 5, 2014

@irace Yep. And, that the input passed by an app doesn't match what another app's extension expects and you get all sorts of weird stuff.

— Federico Viticci (@viticci) September 5, 2014
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

Workaround

This negatively affects both app and extension developers. It means that:

  • App developers should only configure their activity controllers with a single activity item. There are a couple of problems with this.
    1. It’s doable, but a pain if, like in Tumblr.app, you want system activities like copying and saving to the Camera Roll to support multiple different types of data.
    2. It’s a huge shame to only export one type of data and limit the number of sharing options that your users will be able to perform.
  • Extension developers should use the more complex (and unfortunately, not very thoroughly documented) predicate syntax to specifically specify an OR relationship. This would look something like:

SUBQUERY(extensionItems, $extensionItem, SUBQUERY($extensionItem.attachments, $attachment, ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.image").@count <= 10).@count >= 1 OR
SUBQUERY(extensionItems, $extensionItem, SUBQUERY($extensionItem.attachments, $attachment, ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.text").@count >= 1).@count >= 1

@jesseditson
Copy link

Some questions, specific to Tumblr:

I used to use the com.tumblr.photo UTI along with the TumblrTags and TumblrCaption metadata to send posts over to tumblr. I was hoping to be able to send a link and and image with the new extension, but it seems that in addition to being one or the other, it also doesn't have support for tags. Are you aware of any way to send metadata for custom fields over (in your case, tags)? Additionally, I noticed that your app no longer supports metadata with the UIDocumentInteractionController, so although I'm able to open your app, it doesn't initiate a post - we'd love to have that back for our iOS 7 users.

@irace
Copy link
Contributor Author

irace commented Sep 19, 2014

I was hoping to be able to send a link and and image with the new extension

If putting both an NSURL and a UIImage in your activity items array doesn't give you the ability to create a photo post with the URL as the caption, it should. Thanks for the feedback, we'll see if we can make this possible.

It also doesn't have support for tags. Are you aware of any way to send metadata for custom fields over (in your case, tags)?

We could certainly support this, by asking you to create an object with a custom UTI that we specifically look for, and pull whatever different types of metadata that we want out of it. However, the problem with this approach is that only the Tumblr extension will show app, for the very reasons outlined in this issue. Other share extensions won't explicitly support the custom UTI, and as such, won't be displayed in the activity controller.

That said, we'd consider if there's enough demand for specialized, Tumblr-only activity controllers. I'd just be surprised if there was, is all.

Additionally, I noticed that your app no longer supports metadata with the UIDocumentInteractionController, so although I'm able to open your app, it doesn't initiate a post - we'd love to have that back for our iOS 7 users.

This certainly sounds like a bug. I'll file a ticket and take a look, thanks for bringing this to my attention.

@paulrehkugler
Copy link

we'd love to have that back for our iOS 7 users

Our container app with the share extension is iOS 8 only. Was this an issue with the last iOS 7 version?

@jesseditson
Copy link

That all makes a ton of sense to me - for now I'll concat the link & tags in to the text description. I didn't think to check if the new Tumblr was iOS 8, but that should resolve the old version, I'll add the extension support and fall back to the old one on iOS 7!

@rileytestut
Copy link

Did you ever have issues with the predicate simply being parsed incorrectly? I've written a very simple predicate string, yet the Photos app is miserably failing to evaluate it. For instance, you would assume this would allow my extension to be shown whenever a video file is being shared:

SUBQUERY (
    extensionItems,
    $extensionItem,

    SUBQUERY (
        $extensionItem.attachments,
        $attachment,
        ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.movie"
    ).@count >= 1

).@count >= 1

If you select a video in the photos app, and also select a photo that was taken after that video, the extension doesn't appear. However, here's the WTF part: if you select a video, and also a photo taken before that video, it does show up. I cannot come up with any reason why this would be the case, and unfortunately there doesn't seem to be a way to debug how the predicate is being parsed.

I've tried with screenshots, photos from the back camera and the front camera, it doesn't seem to make a difference. The only difference is whether they were taken before or after the shared video.

@irace
Copy link
Contributor Author

irace commented Jun 16, 2015

This is fixed in iOS 9, as per the App Extension Best Practices session 🎉.

To opt your extension into OR instead of AND behavior, simply add the following key/value pair to your Info.plist:

NSExtensionActivationDictionaryVersion: 2

@irace irace closed this as completed Jun 16, 2015
@jasewells
Copy link

The user long-presses on a photo
We put the image data, the posts’s URL, and maybe a text summary of the post, all in the activity items array

Anyone know if the above is the actual behavior of the Tumblr app? I have an action extension that accepts an image, but cannot get it to show up when you long-press a photo. I’ve got NSExtensionActivationSupportsImageWithMaxCount = 1 and NSExtensionActivationDictionaryVersion = 2 in my Info.plist and my extension does appear when doing a similar share from Photos, Twitter, Flickr, etc. But Tumblr only seems to provide a public.url attachment type and nothing matching public.image. (And the link it provides is to the post, not a specific image.) So I’m just wondering if the above idea of providing an image, link, and text together is really being done or if that was just an example/idea and not actually how Tumblr provides activity items.

Incidentally, the standard system “Save Photo” and “Copy” actions do appear from Tumblr, so somehow they know there is image data?

@paulrehkugler
Copy link

You're right; that's not the behavior of the Tumblr app.

In order to avoid having photo posts be unable to be shared by share extensions that do not explicitly support images, we opted for what we assumed to be the lowest common denominator for all share extensions: URLs.

The system copy activity simply acts on the URL of the photo post; if you choose Copy and then paste in a text area, you'll see it's a URL.

The "Save Photo" activity is trickier. Because the system save image activity will not show up based on a URL, we wrote our own custom save image activity that we use when long pressing photos.

@st3fan
Copy link

st3fan commented Oct 18, 2017

@irace It looks like this behaviour again changed in iOS 11. In Firefox for iOS we now have half baked sharing support because our original predicate stopped working. Have you seen anything prblematic with iOS 11?

@irace
Copy link
Contributor Author

irace commented Oct 18, 2017 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants