22

I am trying to add my app to the share sheet. if you look a photo and you press the share button you see Facebook twitter ...

Recently i downloaded a few app from the store and they appear in the share sheet as well so i suppose it possible in some way.

Is it possible? If so how

What this question is not

  1. This is not about simply share data between apps you created. Usually a custom URL scheme is for this purpose, but only when your data source know how to use the custom scheme. But this question is about how to make your app ready for a third party app (i.e. Photos) to share standard content (photos, movies etc) to you.

  2. This is not about how to prepare your content to share on for example Facebook or Twitter. Instead, it asks how to write your own Facebook-like app so it can accept shares

Earth Engine
  • 10,048
  • 5
  • 48
  • 78
nahum
  • 323
  • 2
  • 4
  • 10

2 Answers2

32

Updated for Xcode 11.2.1, swift 5.2

Yes this is possible.


Create an extension

In your XCode go to File -> New -> Target then select Share Extension.

A folder and a file with extension .appex will be created in your project directory.

Folder will contains

Extension Name  --------- ShareViewController.swift
               |
                -------- Maininterface.storyboard 
               |
                -------- Info.plist

Add support for item type

In this plist give proper extensions that your app can share*.

<key>NSExtensionAttributes</key>
    <dict>
        <key>NSExtensionActivationRule</key>
        <dict>
            <key>NSExtensionActivationSupportsImageWithMaxCount</key>
            <integer>10</integer>
            <key>NSExtensionActivationSupportsMovieWithMaxCount</key>
            <integer>1</integer>
            <key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
            <integer>1</integer>
        </dict>
    </dict>

Delegate methods

ShareViewController file content

    override func isContentValid() -> Bool {
            // Do validation of contentText and/or NSExtensionContext attachments here
            return true
    }

    override func didSelectPost() {
             // This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.

            // Inform the host that we're done, so it un-blocks its UI. Note: Alternatively you could call super's -didSelectPost, which will similarly complete the extension context.
                self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
    }

    override func configurationItems() -> [Any]! {
            // To add configuration options via table cells at the bottom of the sheet, return an array of SLComposeSheetConfigurationItem here.
                return []
    }

Sharing the post from your side

You're almost there. Pass the selected item into your app from disSelectPost. You can use an external code below

- ( void ) passSelectedItemsToApp
{
    NSExtensionItem * item = self.extensionContext.inputItems.firstObject;

    // Reset the counter and the argument list for invoking the app:
    m_invokeArgs = NULL;
    m_inputItemCount = item.attachments.count;

    // Iterate through the attached files
    for ( NSItemProvider * itemProvider in item.attachments )
    {
        // Check if we are sharing a JPEG
        if ( [ itemProvider hasItemConformingToTypeIdentifier: ( NSString * ) kUTTypeJPEG ] )
        {
            // Load it, so we can get the path to it
            [ itemProvider loadItemForTypeIdentifier: ( NSString * ) kUTTypeJPEG
                                             options: NULL
                                   completionHandler: ^ ( UIImage * image, NSError * error )
             {
                 static int itemIdx = 0;

                 if ( NULL != error )
                 {
                     NSLog( @"There was an error retrieving the attachments: %@", error );
                     return;
                 }

                 // The app won't be able to access the images by path directly in the Camera Roll folder,
                 // so we temporary copy them to a folder which both the extension and the app can access:
                 NSString * filePath = [ self saveImageToAppGroupFolder: image imageIndex: itemIdx ];

                 // Now add the path to the list of arguments we'll pass to the app:
                 [ self addImagePathToArgumentList: filePath ];

                 // If we have reached the last attachment, it's time to hand control to the app:
                 if ( ++itemIdx >= m_inputItemCount )
                 {
                     [ self invokeApp: m_invokeArgs ];
                 }
             } ];
        }
    }
}

Also make sure you have the extension included in your .ipa file. By opening it using .zip trick.


Debugging your extension

To debug your extension using photos app as you said. You can use the attach to process method. *Steps

1) Open Photos App

2) Attach your extension to xcode using PID or Process name

3) Share a picture or video with your app.

4) App will hit at didSelectPost method.

*Apple documentation

Saranjith
  • 11,242
  • 5
  • 69
  • 122
  • hello. I create Share Extension then i have all file like u? But when run app again, I go to gallery but still can not see my app in share action – kemdo Nov 28 '17 at 17:18
  • are you using simulator or actual device. Have you tried to debug the extension? check didSelectPost working or not – Saranjith Dec 06 '17 at 09:35
  • I'm using a device and i can't see the extension name in the share sheet, any help? – Marouane Lanouari Feb 18 '19 at 16:17
  • Thanks a ton for this, I was struggling to even search for the "I want my app to be a target of a share". The iOS docs are lacking except for API reference. To debug the extension I simply ran the extension and used "photos" as the app to run when it asked. I wasn't sure what you meant by "Attach your extension..." bit. – Chris Feb 24 '19 at 22:07
  • In xcode, goto Debug->Attach select the extension you have created or enter PID – Saranjith Feb 25 '19 at 10:28
  • @kemdo select More You an Able to see If not set attributedRules NSExtensionActivationSupportsImageWithMaxCount = 1 (set number as per count more your need ). If not show if selected count is greater than 2. – kiran Oct 31 '19 at 14:18
  • @Saranjith can we have - ( void ) passSelectedItemsToApp in swift 4.2 – kiran Oct 31 '19 at 14:21
2

@kemdo if your app still invisible - try to click on ellipsis, then you'll see your app and switch near it. that helped me in my case with simulator.

fgrdn
  • 91
  • 1
  • 5