iOS Share Extension — Custom rules to limit type or numbers of medias selected

Chloë Moulinet
3 min readMar 25, 2019

--

I wrote this article as a memo for myself, but since I didn’t find much informations while trying to solve this problem, I though this might help someone.

Recently, I’ve been asked to work on the share extension of our application. The extension was functional, but we needed to prevent the user to share images and videos at the same time.

Precisely the rules we wanted to implement was : user can share 1 <> 20 images OR 1 video.

So our first approach was to set several NSExtensionActivationRules in our info.plist like so (right click on your info.plist file and select open as > source code) :

info.plist from our custom share extension

With this rules we were able to select between 1 and 20 images, but at the same time 1 video. There was no way to set the OR rule.

After a look at Apple’s documentation, I ran into this and this part caught my attention :

App Extension Programming Guide — Declaring Supported Data Types for a Share or Action Extension

What is a Predicate ?

A definition of logical conditions used to constrain a search either for a fetch or for in-memory filtering.

You can learn more about predicates here, but it’s basically a query.

Here is how I built my predicate, this part is the rule to allow the user to select 1 video only :

SUBQUERY (    extensionItems,    $extensionItem,    // First part of the query
SUBQUERY(
$extensionItem.attachments, $attachment, ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.movie" ).@count == 1 AND // Second part of the query
SUBQUERY(
$extensionItem.attachments, $attachment, ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.image" ).@count == 0).@count == 1

Basically the most important part is the bold one. Here I use 2 subqueries to check that the selected items to share:

  • 1. Have a “public.movie” UTI and that the count of items validating this statement equal to 1.
  • 2. And no “public.image” UTI item should be selected (count == 0)

I first try to achieve this by doing something like this :

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

But for some reason it didn’t work (if anyone knows why, I’m suspecting it’s because of the count == 1 but I’m not sure).

Once this was done, the other part was quite easy (adding the OR condition and the other query 1 <> 20 images and no video) :

ORSUBQUERY (    extensionItems,    $extensionItem,    SUBQUERY(         $extensionItem.attachments,         $attachment,         ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO “public.movie”    ).@count == 0    AND    SUBQUERY(    $extensionItem.attachments,    $attachment,    ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO “public.image”    ).@count &lt;= 20).@count &gt;= 1

Make sure to wrap your query with <string> and </string> before you copy it into your info.plist under the <key>NSExtensionActivationRule</key>.

There you are, I’m certainly not an expert on how predicates work so feel free to comment if there is anything wrong or unaccurate in this post.

--

--