How to add extra options to iOS Share Sheet like Safari does

Viewed 716

I am trying to reproduce what Apple does with Safari, where there is a sharing button that allows to share the current page but also provides some extra (and internal) options to do with the page.

For example, we are given options to Add to the reading list, add as bookmark, etc.

enter image description here

These options are exclusive to Safari, as they are not part of the default Share Sheet. How can I hide some of my own app's functionality under a Share Sheet like that?

I did some research and I only found out about custom activities which (as I understand) are the squared buttons that are in the second row of the share sheet (partially hidden in my screenshot).

I also found out about extensions, but I don't think that helps my case, as that allows to customize the share sheet globally for every app, and I need to add options in my app's runtime.

1 Answers

When you initialise a share sheet (aka UIActivityController), you are asked for an array of applicationActivities, that is where your custom internal/share actions will go.

You should just subclass UIActivity, and override the required members as specified by the documentation:

  • activityType
  • activityTitle
  • activityImage
  • canPerform(withActivityItems:)
  • prepare(withActivityItems:)
  • activityCategory

To make your UIActivity appear as a menu button at the bottom of the share sheet, make sure you return .action for activityCategory. If you return .share, it will appear as a square button at the top.

Example:

// dummy implementation
class Foo: UIActivity {
    override var activityTitle: String? { "Foo" }
    override var activityType: UIActivity.ActivityType? { UIActivity.ActivityType("Foo") }
    override var activityImage: UIImage? { UIImage(systemName: "doc.on.doc.fill") }
    override func canPerform(withActivityItems activityItems: [Any]) -> Bool {
        true
    }
    override class var activityCategory: UIActivity.Category { .action }
    override func prepare(withActivityItems activityItems: [Any]) {
        print("Preparing Foo!")
    }
    override func perform() {
        print("Performed Foo!")
    }
}

...

let shareSheet = UIActivityViewController(activityItems: [stuffToShare], applicationActivities: [Foo()])

Output:

enter image description here

If I use .share instead:

enter image description here

Related