Search code examples
iosuiactivityviewcontrollerios-extensions

How to prevent an action extension from appearing in my own iOS app?


I have an iOS app with an action extension that is used to perform actions on images inside other apps when they present UIActivityViewController. Everything is working as intended - if I present an activity sheet in another app, my action extension appears in the list alongside the system actions (such as Save to Files and Create Watch Face etc).

However, the action extension also appears in my own app when I present UIActivityViewController on an image there, which I do not want to happen. Is there any way to prevent my own action extension from appearing in UIActivityViewController inside my own app?

I've tried adding an entry to excludedActivityTypes when presenting UIActivityViewController as follows, but this did not work:

let activity = UIActivityViewController(activityItems: [media], applicationActivities: nil)
activity.excludedActivityTypes = [UIActivity.ActivityType("com.example.ActionExtensionIdentifier")]
// other setup code
present(activity, animated: true)

Solution

  • Here's the solution that I finally used, in case anyone else needs this. (The code was taken from this blog post: https://pspdfkit.com/blog/2016/hiding-action-share-extensions-in-your-own-apps/ so take a look at that too for more details, but the solution I've provided here contains everything that is required to make this work.)

    1. First, create this class

    class ActionExtensionBlockerItem: NSObject, UIActivityItemSource {
        func activityViewController(_ activityViewController: UIActivityViewController, dataTypeIdentifierForActivityType activityType: UIActivity.ActivityType?) -> String {
            return String()
        }
    
        func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
            return NSObject()
        }
    
        func activityViewController(_ activityViewController: UIActivityViewController, subjectForActivityType activityType: UIActivity.ActivityType?) -> String {
            return String()
        }
    
        func activityViewController(_ activityViewController: UIActivityViewController, thumbnailImageForActivityType activityType: UIActivity.ActivityType?, suggestedSize size: CGSize) -> UIImage? {
            return nil
        }
    
        func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
            return String()
        }
    }
    

    2. Apply instance of that class

    When you present UIActivityViewController, create an instance of ActionExtensionBlockerItem and include it in the activityItems array like this:

    func share(_ image: UIImage) {
        let activity = UIActivityViewController(activityItems: [image, ActionExtensionBlockerItem()], applicationActivities: nil)
        activity.popoverPresentationController?.sourceView = view // change to something appropriate for your app
        activity.popoverPresentationController?.sourceRect = view.bounds // change to something appropriate for your app
        present(activity, animated: true)
    }