4

Is it possible to return multiple values from UIActivityItemSource function, and pass them to UIActivityViewController's activityItems?

I want to return [message, image, url] array and pass to activityItems. But the switch code that I used only returns one value, either message, image, or url, depending on which activity is selected, obviously.

If I change: func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? to: func.... -> [Any]?

UIActivityItemSource complains:

"Type 'ActivityItemSource' does not conform to protocol 'UIActivityItemSource'"

and let you insert another set of the same functions with "-> Any?"

Maybe I don't comprehend how to handle init(), but would appreciate it if anyone could give me a direction to solve this.

I found a similar question at Multiple data from UIActivityItemSource and the poster himself figured out as: "Turned out all I needed to do was provide multiple items to the activity controller, since each activity item source can only provide one item."

Does this mean I need to make ActivityItemSource1 class for message, ActivityItemSource2 class for image, ActivityItemSource3 class for url? and assign them to activityItems like this?:

let activityItems = [ActivityItemSource1(message: message), ActivityItemSource2(image: image), ActivityItemSource3(url: url)]

==================================================================

class ActivityItemSource: NSObject, UIActivityItemSource {

var message: String!
var image: UIImage!
var url: URL!

init(message: String, image: UIImage, url: URL) {
    self.message = message
    self.image = image
    self.url = url
}

func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
    return message
}

func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {

    switch activityType {
    case UIActivity.ActivityType.postToFacebook:
        return image
    case UIActivity.ActivityType.postToTwitter:
        return message
    case UIActivity.ActivityType.mail:
        return message
    case UIActivity.ActivityType.copyToPasteboard:
        return message
    case UIActivity.ActivityType.markupAsPDF:
        return message
    case UIActivity.ActivityType.message:
        return message
    case UIActivity.ActivityType.postToFlickr:
        return image
    case UIActivity.ActivityType.postToTencentWeibo:
        return message
    case UIActivity.ActivityType.postToVimeo:
        return image
    case UIActivity.ActivityType.print:
        return message
    case UIActivity.ActivityType(rawValue: "com.apple.reminders.RemindersEditorExtension"):
        return message
    case UIActivity.ActivityType(rawValue: "com.apple.mobilenotes.SharingExtension"):
        return message

    default:
       return message

     }

   }
}


class TodaysTasksTableViewcontroller: TableViewController {
    var image: UIImage
    var message: String
    var url: URL

    image = UIImage(named: "PoliPoliIconLarge")!
    message = "I will complete the following task(s) today :"
    url = URL(string: "http://www.beckos.com")!

let activityItems = [ActivityItemSource(message: message, image: image, url: url)]

    let activityVC =      UIActivityViewController(activityItems: activityItems, applicationActivities: nil)

// Exclude some activities from share popup screen
    activityVC.excludedActivityTypes = [
        UIActivity.ActivityType.assignToContact,
        UIActivity.ActivityType.print,
        UIActivity.ActivityType.addToReadingList,
        UIActivity.ActivityType.saveToCameraRoll,
        UIActivity.ActivityType.openInIBooks,
        //UIActivity.ActivityType(rawValue: "com.apple.reminders.RemindersEditorExtension"),
        //UIActivity.ActivityType(rawValue: "com.apple.mobilenotes.SharingExtension"),
    ]


    self.present(activityVC, animated: true, completion: nil)

................
    }
Sigabrt M
  • 71
  • 6
  • https://stackoverflow.com/questions/20694382/multiple-uiactivityviewcontroller-placeholder-items ? https://stackoverflow.com/questions/13029340/uiactivityitemsource-protocole-set-complex-object ? – Larme Dec 04 '18 at 11:27

2 Answers2

3

This is what I did last night. I am not sure if this way is efficient in terms of proper coding style, though. Also I'm not sure if I truly understand the way ActivitySourceItems works. Somebody probably can write it much more efficient way.

Basically I created three classes, one for message, one for image, and one for url. then pass three returns to a constant, activityItems. Still Instagram and Snapchat don't work with this, though. beside that, It does what I wanted to do anyway.

Thanx for the links, Larme. My previous search didn't show up these postings.

class TableViewController: UITableViewController {     
    let activityItems = [ActivityItemSource(message: message),    ActivityItemSourceImage(image: image), ActivityItemSourceURL(url: url)]
    let activityVC = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)

    // some exclusion goes here...

    self.present(activityVC, animated: true, completion: nil)

}

class ActivityItemSource: NSObject, UIActivityItemSource {

    var message: String!

    init(message: String) {
        self.message = message
    }

    func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
        return message
        // to display Instagram button, return image
        // image: Mail, Message, Notes, Twitter, Instagram, Shared Album, Post to Google Maps, Messenger, LINE, Snapchat, Facebook
        // message: Mail, Message, Notes, Twitter, Messenger, LINE, Facebook, LinkedIn
    }

    func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {

        switch activityType {
        case UIActivity.ActivityType.postToFacebook:
            return nil
        case UIActivity.ActivityType.postToTwitter:
            return message
        case UIActivity.ActivityType.mail:
            return message
        case UIActivity.ActivityType.copyToPasteboard:
            return message
        case UIActivity.ActivityType.markupAsPDF:
            return message
        case UIActivity.ActivityType.message:
            return message
        case UIActivity.ActivityType.postToFlickr:
            return message
        case UIActivity.ActivityType.postToTencentWeibo:
            return message
        case UIActivity.ActivityType.postToVimeo:
            return message
        case UIActivity.ActivityType.print:
            return message
        case UIActivity.ActivityType(rawValue: "com.apple.reminders.RemindersEditorExtension"):
            return message
        case UIActivity.ActivityType(rawValue: "com.apple.mobilenotes.SharingExtension"):
            return message
        case UIActivity.ActivityType(rawValue: "com.burbn.instagram.shareextension"):
            return nil
        case UIActivity.ActivityType(rawValue: "jp.naver.line.Share"):
            return message

        default:
            return nil
        }
    }
}


class ActivityItemSourceImage: NSObject, UIActivityItemSource {

    var image: UIImage!


    init(image: UIImage) {
        //self.image = image
        self.image = UIImage(named: "PoliPoliIcon")!

    }


    func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
        return image
    }

    func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {


        switch activityType {
        case UIActivity.ActivityType.postToFacebook:
            return nil
        case UIActivity.ActivityType.postToTwitter:
            return nil
        case UIActivity.ActivityType.mail:
            return image
        case UIActivity.ActivityType.copyToPasteboard:
            return image
        case UIActivity.ActivityType.markupAsPDF:
            return image
        case UIActivity.ActivityType.message:
            return image
        case UIActivity.ActivityType.postToFlickr:
            return image
        case UIActivity.ActivityType.postToTencentWeibo:
            return image
        case UIActivity.ActivityType.postToVimeo:
            return image
        case UIActivity.ActivityType.print:
            return image
        case UIActivity.ActivityType(rawValue: "com.apple.reminders.RemindersEditorExtension"):
            return nil
        case UIActivity.ActivityType(rawValue: "com.apple.mobilenotes.SharingExtension"):
            return nil
        case UIActivity.ActivityType(rawValue: "com.burbn.instagram.shareextension"):
            return image
        case UIActivity.ActivityType(rawValue: "jp.naver.line.Share"):
            return image
        default:
            return image

        }
    }

}


class ActivityItemSourceURL: NSObject, UIActivityItemSource {

    var url: URL!


    init(url: URL) {
        self.url = url
    }

    func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
        return url

    }

    func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {

        switch activityType {
        case UIActivity.ActivityType.postToFacebook:
            return url
        case UIActivity.ActivityType.postToTwitter:
            return url
        case UIActivity.ActivityType.mail:
            return url
        case UIActivity.ActivityType.copyToPasteboard:
            return nil
        case UIActivity.ActivityType.message:
            return url
        case UIActivity.ActivityType.postToFlickr:
            return url
        case UIActivity.ActivityType.postToTencentWeibo:
            return url
        case UIActivity.ActivityType.postToVimeo:
            return url
        case UIActivity.ActivityType.print:
            return url
        case UIActivity.ActivityType(rawValue: "com.apple.reminders.RemindersEditorExtension"):
            return url
        case UIActivity.ActivityType(rawValue: "com.apple.mobilenotes.SharingExtension"):
            return url
        case UIActivity.ActivityType(rawValue: "com.burbn.instagram.shareextension"):
            return nil
        case UIActivity.ActivityType(rawValue: "jp.naver.line.Share"):
            return url
        //case UIActivity.ActivityType(rawValue: "com.snapchat.Share"):
          //  return nil

        default:
            return url

        }
    }
}
Sigabrt M
  • 71
  • 6
2

In my case I always want to share an image but I also include a message (String) that contains a URL as part of the message when sharing on certain platforms that allow it. By default I don't display an image because some apps strip out the image if the message contains a URL.

I've created two classes of UIActivityItemSource for the message string and the image:

class MessageActivityItemSource: NSObject, UIActivityItemSource {

    var message: String

    init(_ message: String) {
        self.message = message
    }

    func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
        message
    }

    func activityViewController(_ activityViewController: UIActivityViewController,
                                itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
        switch activityType {
        case
            UIActivity.ActivityType.message,
            UIActivity.ActivityType.postToTwitter,
            UIActivity.ActivityType.mail,
            UIActivity.ActivityType.copyToPasteboard,
            UIActivity.ActivityType.discord,
            UIActivity.ActivityType.viber,
            UIActivity.ActivityType.telegram,
            UIActivity.ActivityType.line:
                return message

        default: return nil
        }
    }
}

class ImageActivityItemSource: NSObject, UIActivityItemSource {

    var image: UIImage

    init(_ image: UIImage) {
        self.image = image
    }

    func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
        image
    }

    func activityViewController(_ activityViewController: UIActivityViewController,
                                itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
        image
    }
}

I also have this small extension so I can detect some of the other apps:

extension UIActivity.ActivityType {

    static let discord = UIActivity.ActivityType(rawValue: "com.hammerandchisel.discord.Share")
    static let viber = UIActivity.ActivityType(rawValue: "com.viber.app-share-extension")
    static let telegram = UIActivity.ActivityType(rawValue: "ph.telegra.Telegraph.Share")
    static let line = UIActivity.ActivityType(rawValue: "jp.naver.line.Share")
}

and then present the share screen:

let activityItems = [
    ImageActivityItemSource(someUIImage),
    MessageActivityItemSource("Some text with included URL https://someApp.com/")
]

let activityVC = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)

activityVC.excludedActivityTypes = [
    .assignToContact,
    .addToReadingList,
    .print,
    .postToVimeo,
    .markupAsPDF,
    .postToFlickr
]

present(activityVC, animated: true, completion: nil)
budiDino
  • 13,044
  • 8
  • 95
  • 91