3

I'm trying to customize the native ios UIActivityViewController so it will restrict every UIActivity except for the custom UIActivity types that I initialize the UIActivityViewController with.

Essentially, I only want the user to see my four custom UIActivitys.

let items = ["Hello world"]

let activitySheet = CustomUIActivityViewController(
            activityItems: items,
            applicationActivities: [
                CustomMailUIActivity(),
                CustomMessagesUIActivity(),
                CustomTwitterUIActivity(),
                CustomFacebookUIActivity()
            ]
        )

I understand that you can use activitySheet.excludedActivityTypes = [] to exclude types that you do not need, however you are not able to exclude third party applications such as Slack.

I was wondering if there was any way to get around that and ONLY include custom applicationActivies. It would also be great to remove the "More" button that appears on the share sheet as well. Any help would be greatly appreciated.

This is what I'm trying to achieve.

screenshot

ceylonese92
  • 93
  • 2
  • 10
  • Unfortunately `UIActivityViewController ` doesn't make this easy. You need to list all of the activities you wish to exclude and some can't be excluded. See https://stackoverflow.com/questions/31792506/how-to-exclude-notes-and-reminders-apps-from-the-uiactivityviewcontroller for some ideas to get close. – rmaddy Mar 13 '19 at 21:46

1 Answers1

4

My colleague was able to figure this out. For anyone wondering how to display only the applicationActivities (custom activities) on the share sheet, this is how I did it.

For activityItems rather than creating an array of strings, create an array of your custom data objects. Then override the canPerform(withActivityItems activityItems: [Any]) method in your custom UIActivity (subclass of UIActivity) to return true if activityItems[o] is CustomItem. Since your activityItems are custom, system will not display other apps on the share sheet. That's it.

In the example below, only your CustomUIActivity will be displayed on the share sheet.

let items = [CustomItem("Hello world")]

let activitySheet = UIActivityViewController(
            activityItems: items,
            applicationActivities: [
                CustomUIActivity()
            ]
        )
class CustomItem {

    let value: String

    required init(value: String) {
        self.value = value
    }

    func getValue() -> String {
        return self.value
    }
}
@objc(CustomUIActivity)
class CustomUIActivity: UIActivity {

    override class var activityCategory: UIActivity.Category {
        return .share
    }

    override var activityType: UIActivity.ActivityType? {
        return .customuiactivity
    }

    override var activityTitle: String? {
        return "Custom"
    }

    override var activityImage: UIImage? {
        return UIImage(named: "custom-icon")
    }

    override func canPerform(withActivityItems activityItems: [Any]) -> Bool {
        if activityItems.count == 1 && activityItems[0] is CustomItem {
            return true
        }
        return false
    }

    var textToShare: String?

    override func prepare(withActivityItems activityItems: [Any]) {
        if let activityItem = activityItems.first as? CustomItem {
            self.textToShare = activityItem.getValue
        }
    }

    override func perform() {
        // perform your custom activity with `textToShare`
        activityDidFinish(true)
    }
}

extension UIActivity.ActivityType {
    static let customuiactivity =
        UIActivity.ActivityType("com.ceylonese.mobile.customuiactivity")
}
ceylonese92
  • 93
  • 2
  • 10
  • Thanks for your answer! Did you also figure out how to only show actions? So something that looks like the e.g. "Copy"-Action on a regular UIActivityViewController? – Georg Mar 30 '21 at 12:47
  • If I want to share content using only some 2-3 apps, say Gmail, WhatsApp and Mail app.. is it possible using this approach? Thanks – letsbondiway Jul 14 '22 at 14:51