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)
................
}
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
}
}
}
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With