UIActivityViewController chose different text for WhatsApp or Facebook - ios

I have the text in activity Items but now it share on WhatsApp or Facebook, this method share for each app the same text.
is it possible to share different text for each app ?
- (void)share {
NSString *text = #"share test";
NSArray * activityItems = #[[NSString stringWithFormat:#"%#", text], [NSURL URLWithString:#"http://www.test.co"]];
NSArray * applicationActivities = nil;
NSArray * excludeActivities = #[UIActivityTypeAssignToContact, UIActivityTypeCopyToPasteboard, UIActivityTypePostToWeibo, UIActivityTypePrint, UIActivityTypeMessage];
UIActivityViewController * activityController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:applicationActivities];
activityController.excludedActivityTypes = excludeActivities;
[self presentViewController:activityController animated:YES completion:nil];
[activityController setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
NSLog(#"The setCompletionWithItemsHandler completed = %i", completed);
if (completed) {
NSLog(#"The selected activity was %#", activityType);
if ( [activityType isEqualToString:UIActivityTypeMail]) {
NSLog(#"Mail sended");
} else if ( [activityType isEqualToString:UIActivityTypePostToTwitter]) {
NSLog(#"Post on twitter, ok!");
} else if ( [activityType isEqualToString:UIActivityTypePostToFacebook]) {
NSLog(#"Post on facebook, ok!");
} else if ( [activityType isEqualToString:UIActivityTypeMessage]) {
NSLog(#"SMS sended!");
}
}
}];
}

Short answer: Yes!
There is actually a way to return different content for multiple apps, AFTER choosing them.
You will have to create two UIActivityItemSource, one which will return an UIImage and other which will return a NSObject. This is done to "fool" the system that you will share these objects, but after the user has selected an app, we can actually return something else, like a URL.
class SocialActivityItem: NSObject, UIActivityItemSource {
var img: UIImage?
var url: URL?
convenience init(img: UIImage, url: URL) {
self.init()
self.img = img
self.url = url
}
// This will be called BEFORE showing the user the apps to share (first step)
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
return img!
}
// This will be called AFTER the user has selected an app to share (second step)
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivityType?) -> Any? {
//Instagram
if activityType?.rawValue == "com.burbn.instagram.shareextension" {
return img!
} else {
return url
}
}
}
and
class TextActivityItem: NSObject, UIActivityItemSource {
var textToShare: String?
convenience init(textToShare: String) {
self.init()
self.textToShare = textToShare
}
// This will be called BEFORE showing the user the apps to share (first step)
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
return NSObject()
}
// This will be called AFTER the user has selected an app to share (second step)
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivityType?) -> Any? {
var text = ""
if activityType?.rawValue == "net.whatsapp.WhatsApp.ShareExtension" {
text = "Sharing on Whatsapp"
}
if activityType == UIActivityType.postToFacebook {
text = "Sharing on Facebook"
}
return text.isEmpty ? textToShare : text
}
}
Then, you just need to set everything up:
let url = URL(string: "www.google.com")!
let socialProvider = SocialActivityItem(img: img, url: url)
let textProvider = TextActivityItem(textToShare: "Sharing on social media!")
let activityViewController = UIActivityViewController(activityItems: [socialProvider, textProvider], applicationActivities: nil)

Short answer: No.
But you can use the open App with URL method and pass an parameter to that App.
When using that method you have to use a custom UI and can not use the UIActivityViewController. (As far as i know)
So, it is possible, if you want to have multiple buttons like:
"Share with WhatsApp"
"Share with Facebook"
etc.

Related

How to set different parameters in WhatsApp sharing with UIActivityViewController in iOS Swift?

I am using UIActivityViewController for sharing contents from app.
I want to share different content with different sharing apps.
Like in Message output will be like this.image + text + URL
in Whatsapp i would like to share like below image text + URL
How can i do this? See below screen shots for this.
It took me a good time figuring this out, but that's how it worked for me:
Think of this problem in two steps: first, we need to tell to the UIActivityViewController which content we want to share. Second, we need to return the content based on each social media, either a link, an image or a text. Its up to the social media app to tell which content it can handle, and it will only show up if we share the right kind of content.
In the first step, we will try to fool the social media apps, saying that we want to share an UIImage and a NSObject. This will open most of the social media apps to share.
In the second step, we will identify which social media app the user has clicked, and return the appropriated content for it.
Implementation:
create two UIActivityItemSource, one which will return an UIImage and other which will return the NSObject.
class SocialActivityItem: NSObject, UIActivityItemSource {
var img: UIImage?
var url: URL?
convenience init(img: UIImage, url: URL) {
self.init()
self.img = img
self.url = url
}
// This will be called BEFORE showing the user the apps to share (first step)
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
return img!
}
// This will be called AFTER the user has selected an app to share (second step)
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivityType?) -> Any? {
//Instagram
if activityType?.rawValue == "com.burbn.instagram.shareextension" {
return img!
} else {
return url
}
}
}
and
class TextActivityItem: NSObject, UIActivityItemSource {
var textToShare: String?
convenience init(textToShare: String) {
self.init()
self.textToShare = textToShare
}
// This will be called BEFORE showing the user the apps to share (first step)
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
return NSObject()
}
// This will be called AFTER the user has selected an app to share (second step)
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivityType?) -> Any? {
var text = ""
if activityType?.rawValue == "net.whatsapp.WhatsApp.ShareExtension" {
text = "Sharing on Whatsapp"
}
if activityType == UIActivityType.postToFacebook {
text = "Sharing on Facebook"
}
return text
}
}
Then, you just need to set everything up:
let url = URL(string: "www.google.com")!
let socialProvider = SocialActivityItem(img: img, url: url)
let textProvider = TextActivityItem(textToShare: "Sharing on social media!")
let activityViewController = UIActivityViewController(activityItems: [socialProvider, textProvider], applicationActivities: nil)

Swift : Share image using UIActivityViewController

I want to share QR image on tap of button using ActivityViewController.
Below is code that I’ve used :
#IBAction func btnShareQRCode_Clicked(sender: UIButton) {
self.shareQRCodeUsingActivityViewController(self.imageviewQRCode.image!)
}
func shareQRCodeUsingActivityViewController(imageParamater: UIImage) {
let activityItem: [UIImage] = [imageParamater as UIImage]
let objActivityViewController = UIActivityViewController(activityItems: activityItem as [UIImage], applicationActivities: nil)
objActivityViewController.excludedActivityTypes = [UIActivityTypeAirDrop, UIActivityTypeAddToReadingList]
// objActivityViewController.popoverPresentationController?.sourceView = sender
self.presentViewController(objActivityViewController, animated: true, completion: {
objActivityViewController.completionWithItemsHandler = { activity, success, items, error in
if !success { print("cancelled")
return
}
if activity == UIActivityTypeMail {
print("mail")
}
else if activity == UIActivityTypeMessage {
print("message")
}
else if activity == UIActivityTypeSaveToCameraRoll {
print("camera")
}
}
})
}
func completionHandler() {
}
The issue with this is that it is getting crashed on mail stating an error regarding MailComposer.
I want to know how and where these MailComposer function should be handled?
If you are running this on iOS Simulator, Mail component is likely to fail.
Apart from that, I don't think you need to cast your activity items list as UIImage. Simply put an array of objects as a activityItems array.

Open an Alert asking to choose App to open map with

I have a view controller with map kit integrated. I need to shoot an alert before opening that map, asking to choose from all similar applications of maps to open it with. For instance, if google maps app is installed in my iPhone, there should be an option for it, along with the default mapkit view. Is there a possibility to achieve this functionality which scans every similar app from iphone and returns the result as options to open map with.
You can create an array of checks to map the installed apps using sumesh's answer [1]:
var installedNavigationApps : [String] = ["Apple Maps"] // Apple Maps is always installed
and with every navigation app you can think of:
if (UIApplication.sharedApplication().canOpenURL(url: NSURL)) {
self.installedNavigationApps.append(url)
} else {
// do nothing
}
Common navigation apps are:
Google Maps - NSURL(string:"comgooglemaps://")
Waze - NSURL(string:"waze://")
Navigon - NSURL(string:"navigon://")
TomTom - NSURL(string:"tomtomhome://")
A lot more can be found at: http://wiki.akosma.com/IPhone_URL_Schemes
After you created your list of installed navigation apps you can present an UIAlertController:
let alert = UIAlertController(title: "Selection", message: "Select Navigation App", preferredStyle: .ActionSheet)
for app in self.installNavigationApps {
let button = UIAlertAction(title: app, style: .Default, handler: nil)
alert.addAction(button)
}
self.presentViewController(alert, animated: true, completion: nil)
Of course you need to add the behavior of a button click in the handler with the specified urlscheme. For example if Google Maps is clicked use something like this:
UIApplication.sharedApplication().openURL(NSURL(string:
"comgooglemaps://?saddr=&daddr=\(place.latitude),\(place.longitude)&directionsmode=driving")!) // Also from sumesh's answer
With only Apple Maps and Google Maps installed this will yield something like this:
Swift 5+
Base on #Emptyless answer.
import MapKit
func openMapButtonAction() {
let latitude = 45.5088
let longitude = -73.554
let appleURL = "http://maps.apple.com/?daddr=\(latitude),\(longitude)"
let googleURL = "comgooglemaps://?daddr=\(latitude),\(longitude)&directionsmode=driving"
let wazeURL = "waze://?ll=\(latitude),\(longitude)&navigate=false"
let googleItem = ("Google Map", URL(string:googleURL)!)
let wazeItem = ("Waze", URL(string:wazeURL)!)
var installedNavigationApps = [("Apple Maps", URL(string:appleURL)!)]
if UIApplication.shared.canOpenURL(googleItem.1) {
installedNavigationApps.append(googleItem)
}
if UIApplication.shared.canOpenURL(wazeItem.1) {
installedNavigationApps.append(wazeItem)
}
let alert = UIAlertController(title: "Selection", message: "Select Navigation App", preferredStyle: .actionSheet)
for app in installedNavigationApps {
let button = UIAlertAction(title: app.0, style: .default, handler: { _ in
UIApplication.shared.open(app.1, options: [:], completionHandler: nil)
})
alert.addAction(button)
}
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alert.addAction(cancel)
present(alert, animated: true)
}
Also put these in your info.plist:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>googlechromes</string>
<string>comgooglemaps</string>
<string>waze</string>
</array>
Cheers!
Swift 5+ solution based on previous answers, this one shows a selector between Apple Maps, Google Maps, Waze and City Mapper. It also allows for some optional location title (for those apps that support it) and presents the alert only if there are more than 1 option (it opens automatically if only 1, or does nothing if none).
func openMaps(latitude: Double, longitude: Double, title: String?) {
let application = UIApplication.shared
let coordinate = "\(latitude),\(longitude)"
let encodedTitle = title?.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
let handlers = [
("Apple Maps", "http://maps.apple.com/?q=\(encodedTitle)&ll=\(coordinate)"),
("Google Maps", "comgooglemaps://?q=\(coordinate)"),
("Waze", "waze://?ll=\(coordinate)"),
("Citymapper", "citymapper://directions?endcoord=\(coordinate)&endname=\(encodedTitle)")
]
.compactMap { (name, address) in URL(string: address).map { (name, $0) } }
.filter { (_, url) in application.canOpenURL(url) }
guard handlers.count > 1 else {
if let (_, url) = handlers.first {
application.open(url, options: [:])
}
return
}
let alert = UIAlertController(title: R.string.localizable.select_map_app(), message: nil, preferredStyle: .actionSheet)
handlers.forEach { (name, url) in
alert.addAction(UIAlertAction(title: name, style: .default) { _ in
application.open(url, options: [:])
})
}
alert.addAction(UIAlertAction(title: R.string.localizable.cancel(), style: .cancel, handler: nil))
contextProvider.currentViewController.present(alert, animated: true, completion: nil)
}
Note this solution uses R.swift for string localization but you can replace those with NSLocalizedString normally, and it uses a contextProvider.currentViewController to get the presented UIViewController, but you can replace it with self if you are calling this in a view controller already.
As usual, you need to also add the following to your app Info.plist:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>citymapper</string>
<string>comgooglemaps</string>
<string>waze</string>
</array>
A SwiftUI approach based on #Angel G. Olloqui answer:
struct YourView: View {
#State private var showingSheet = false
var body: some View {
VStack {
Button(action: {
showingSheet = true
}) {
Text("Navigate")
}
}
.actionSheet(isPresented: $showingSheet) {
let latitude = 45.5088
let longitude = -73.554
let appleURL = "http://maps.apple.com/?daddr=\(latitude),\(longitude)"
let googleURL = "comgooglemaps://?daddr=\(latitude),\(longitude)&directionsmode=driving"
let wazeURL = "waze://?ll=\(latitude),\(longitude)&navigate=false"
let googleItem = ("Google Map", URL(string:googleURL)!)
let wazeItem = ("Waze", URL(string:wazeURL)!)
var installedNavigationApps = [("Apple Maps", URL(string:appleURL)!)]
if UIApplication.shared.canOpenURL(googleItem.1) {
installedNavigationApps.append(googleItem)
}
if UIApplication.shared.canOpenURL(wazeItem.1) {
installedNavigationApps.append(wazeItem)
}
var buttons: [ActionSheet.Button] = []
for app in installedNavigationApps {
let button: ActionSheet.Button = .default(Text(app.0)) {
UIApplication.shared.open(app.1, options: [:], completionHandler: nil)
}
buttons.append(button)
}
let cancel: ActionSheet.Button = .cancel()
buttons.append(cancel)
return ActionSheet(title: Text("Navigate"), message: Text("Select an app..."), buttons: buttons)
}
}
}
Also, add the following to your Info.plist
<key>LSApplicationQueriesSchemes</key>
<array>
<string>googlechromes</string>
<string>comgooglemaps</string>
<string>waze</string>
</array>
For anyone else looking for something similar
you can now use UIActivityViewController, its the same UIControl Photos or Safari use when you click on the share button.
For apple maps and google maps you can add custom application activity to show alongside the other items. You need to subclass UIActivity and override the title and image methods. And the perform() function to handle the tap on our custom item
below is Objective C code i wrote for the same.
For Swift code you can refer UIActivityViewController swift
NSMutableArray *activityArray = [[NSMutableArray alloc] init];
// Check if google maps is installed and accordingly add it in menu
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:#"comgooglemaps://"]]) {
GoogleMapsActivityView *googleMapsActivity = [[GoogleMapsActivityView alloc] init];
[activityArray addObject:googleMapsActivity];
}
// Check if apple maps is installed and accordingly add it in menu
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:#"maps://"]]) {
AppleMapsActivityView *appleMapsActivity = [[AppleMapsActivityView alloc] init];
[activityArray addObject:appleMapsActivity];
}
NSArray *currentPlaces = [NSArray arrayWithObject:place];
UIActivityViewController *activityViewController =
[[UIActivityViewController alloc] initWithActivityItems:currentPlaces
applicationActivities:activityArray];
activityViewController.excludedActivityTypes = #[UIActivityTypePrint,
UIActivityTypeCopyToPasteboard,
UIActivityTypeAssignToContact,
UIActivityTypeSaveToCameraRoll,
UIActivityTypePostToWeibo,
UIActivityTypeAddToReadingList,
UIActivityTypePostToVimeo,
UIActivityTypeAirDrop];
[self presentViewController:activityViewController animated:YES completion:nil];
And Subclass the GoogleMapsActivity
#interface GoogleMapsActivityView: UIActivity
#end
#implementation GoogleMapsActivityView
- (NSString *)activityType {
return #"yourApp.openplace.googlemaps";
}
- (NSString *)activityTitle {
return NSLocalizedString(#"Open with Google Maps", #"Activity view title");
}
- (UIImage *)activityImage {
return [UIImage imageNamed:#"ic_google_maps_logo"];
}
- (UIActivityCategory)activityCategory {
return UIActivityCategoryAction;
}
- (BOOL)canPerformWithActivityItems:(NSArray *)activityItems {
return YES;
}
- (void)performActivity {
CLLocationDegrees lat = 99999;
CLLocationDegrees lng = 99999;
NSString *latlong = [NSString stringWithFormat:#"%.7f,%#%.7f", lat, #"", lng];
NSString *urlString = [NSString stringWithFormat:#"comgooglemaps://?q=%#", latlong];
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:urlString]]) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]
options:#{}
completionHandler:nil];
}
[self activityDidFinish:YES];
}
SwiftUI rewrite from previous solutions using enums and a view modifier
extension View {
func opensMap(at location: LocationCoordinate2D) -> some View {
return self.modifier(OpenMapViewModifier(location: location))
}
}
struct OpenMapViewModifier: ViewModifier {
enum MapApp: CaseIterable {
case apple, gmaps
var title: String {
switch self {
case .apple: return "Apple Maps"
case .gmaps: return "Google Maps"
}
}
var scheme: String {
switch self {
case .apple: return "http"
case .gmaps: return "comgooglemaps"
}
}
var isInstalled: Bool {
guard let url = URL(string: self.scheme.appending("://")) else { return false }
return UIApplication.shared.canOpenURL(url)
}
func url(for location: LocationCoordinate2D) -> URL? {
switch self {
case .apple:
return URL(string: "\(self.scheme)://maps.apple.com/?daddr=\(location.latitude),\(location.longitude)")
case .gmaps:
return URL(string: "\(self.scheme)://?daddr=\(location.latitude),\(location.longitude)&directionsmode=driving")
}
}
}
var location: LocationCoordinate2D
#State private var showingAlert: Bool = false
private let installedApps = MapApp.allCases.filter { $0.isInstalled }
func body(content: Content) -> some View {
Button(action: {
if installedApps.count > 1 {
showingAlert = true
} else if let app = installedApps.first, let url = app.url(for: location) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}) {
content.actionSheet(isPresented: $showingAlert) {
let appButtons: [ActionSheet.Button] = self.installedApps.compactMap { app in
guard let url = app.url(for: self.location) else { return nil }
return .default(Text(app.title)) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}
return ActionSheet(title: Text("Navigate"), message: Text("Select an app..."), buttons: appButtons + [.cancel()])
}
}
}
}

Share via AirDrop only

I want to bring out the share sheet with the AirDrop as the only option in my application.
In iOS 7, I could simple add all share types to the excludedActivityTypes property of UIActivityViewController (UIActivityTypeMessage, UIActivityTypeMail, ...)
But now in iOS 8, with the app extensions, the users may have extra sharing providers that show up.
Is there any way to show AirDrop only?
UIActivityViewController *controller = [[UIActivityViewController alloc] initWithActivityItems:#[[NSURL URLWithString:url]]
applicationActivities:nil];
NSArray *excludedActivities = #[UIActivityTypePostToTwitter, UIActivityTypePostToFacebook,
UIActivityTypePostToWeibo,
UIActivityTypeMessage, UIActivityTypeMail,
UIActivityTypePrint, UIActivityTypeCopyToPasteboard,
UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll,
UIActivityTypeAddToReadingList, UIActivityTypePostToFlickr,
UIActivityTypePostToVimeo, UIActivityTypePostToTencentWeibo];
class AirDropOnlyActivityItemSource : NSObject, UIActivityItemSource {
/// The item you want to send via AirDrop.
let item: AnyObject
init(item: AnyObject) {
self.item = item
}
func activityViewControllerPlaceholderItem(activityViewController: UIActivityViewController) -> AnyObject {
/// Use an empty URL as placeholder to let iOS Share Sheet show the AirDrop only.
return NSURL(string: "")!
}
func activityViewController(activityViewController: UIActivityViewController, itemForActivityType activityType: String) -> AnyObject? {
return item
}
}
Swift 4.2 version of Jonny's answer:
class AirDropOnlyActivityItemSource: NSObject, UIActivityItemSource {
///The item you want to send via AirDrop.
let item: Any
init(item: Any) {
self.item = item
}
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
//using NSURL here, since URL with an empty string would crash
return NSURL(string: "")!
}
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
return item
}
}
Usage:
let itemSource = AirDropOnlyActivityItemSource(item: "test")
let activityVc = UIActivityViewController(activityItems: [itemSource], applicationActivities: nil)
That's currently not possible. You should file an enhancement request with apple explaining why this would be useful to the user/developer.

UIActivityViewController completion handler still calls action if user presses cancel

In my UIActivityViewController, I use completion handler to execute a "successfully shared" notification. It works but my only problem is, it still shows the notification if the user presses cancel.
Here is my completion handler code,
[controller setCompletionHandler:^(NSString *activityType, BOOL completed) {
CWStatusBarNotification *notification = [CWStatusBarNotification new];
[notification displayNotificationWithMessage:#"✓ Successfully Shared Centre!"
forDuration:3.0f];
notification.notificationLabelBackgroundColor = [UIColor colorWithRed:38.0f/255.0f green:81.0f/255.0f blue:123.0f/255.0f alpha:1.0f];
notification.notificationLabelTextColor = [UIColor whiteColor];
}];
Thanks for the help!
Note: the completionHandler property is deprecated in iOS8, so it's not possible anymore to know the result of a share action.
https://developer.apple.com/documentation/uikit/uiactivityviewcontroller/1622010-completionhandler
Update:
Like adruzh said, on iOS8 there's a new completionHandler that Apple forgot to mention in the documentation:
[activityController setCompletionWithItemsHandler:
^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
}];
https://developer.apple.com/documentation/uikit/uiactivityviewcontroller/1622022-completionwithitemshandler
That's what the completed argument is for:
[controller setCompletionHandler:^(NSString *activityType, BOOL completed) {
if (!completed) return;
CWStatusBarNotification *notification = [CWStatusBarNotification new];
[notification displayNotificationWithMessage:#"✓ Successfully Shared Centre!"
forDuration:3.0f];
notification.notificationLabelBackgroundColor = [UIColor colorWithRed:38.0f/255.0f green:81.0f/255.0f blue:123.0f/255.0f alpha:1.0f];
notification.notificationLabelTextColor = [UIColor whiteColor];
}];
For Swift, this is what worked for us:
...
// Configure UIActivityViewController
let activityViewController = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
activityViewController.excludedActivityTypes = [UIActivityTypeAirDrop,
UIActivityTypeAddToReadingList,
UIActivityTypeAssignToContact,
UIActivityTypePrint,
UIActivityTypeCopyToPasteboard]
// Show UIActivityViewController
presentViewController(activityViewController, animated: true, completion: nil)
// Define completion handler
activityViewController.completionWithItemsHandler = doneSharingHandler
...
func doneSharingHandler(activityType: String!, completed: Bool, returnedItems: [AnyObject]!, error: NSError!) {
// Return if cancelled
if (!completed) {
return
}
// If here, log which activity occurred
println("Shared video activity: \(activityType)")
}
Swift 5 - The below function covers most of the UIActivityViewController properties. It worked for me and thought so it might be helpful for you guys as well.
func performShareAction() {
let itemsToShare : [Any] = ["Hello World"]
let activityView = UIActivityViewController(activityItems: itemsToShare, applicationActivities: nil)
// Apps that you want to exclude sharing the items
let excludedActivityTypes : [UIActivity.ActivityType] = [
.addToReadingList,
.assignToContact,
.copyToPasteboard,
.mail,
.markupAsPDF,
.message,
.openInIBooks,
.postToFacebook,
.postToFlickr,
.postToTencentWeibo,
.postToTwitter,
.postToVimeo,
.postToWeibo,
.print,
.saveToCameraRoll
]
activityView.excludedActivityTypes = excludedActivityTypes
self.present(activityView, animated: true, completion: nil)
activityView.completionWithItemsHandler = { activityType, completed, items, error in
// Event Cancelled
if !completed {
print("Content Sharing was cancelled.")
return
}
// Content Shared on particular activity
print("Shared on activity type: \(String(describing: activityType?.rawValue))")
// Detect app on which the items are shared
if let type = activityType {
switch type {
case .addToReadingList: print("Added To Reading List"); break
case .airDrop: print("AirDropped to Other Device"); break
case .assignToContact: print("Assigned To Contact"); break
case .copyToPasteboard: print("Copied To Pasteboard"); break
case .mail: print("Mailed"); break
case .markupAsPDF: print("Marked-Up As PDF"); break
case .message: print("Messaged"); break
case .openInIBooks: print("Opened In iBooks"); break
case .postToFacebook: print("Posted To Facebook"); break
case .postToFlickr: print("Posted To Flickr"); break
case .postToTencentWeibo: print("Posted To Tencent Weibo"); break
case .postToTwitter: print("Posted To Twitter"); break
case .postToVimeo: print("Posted To Vimeo"); break
case .postToWeibo: print("Posted To Weibo"); break
case .print: print("Printed"); break
case .saveToCameraRoll: print("Saved To Camera Roll"); break
default: print("Shared with new app"); break
}
}
}
}
For the Swifties out there, here's how you would code this in Swift along with some share service detection:
activityViewController.completionHandler = {(activityType, completed:Bool) in
if !completed {
//cancelled
return
}
//shared successfully
//below is how you would detect for different sharing services
var activity:String = "other"
if activityType == UIActivityTypePostToTwitter {
activity = "twitter"
}
if activityType == UIActivityTypeMail {
activity = "mail"
}
//more code here if you like
}
The completed parameter will be NO is the user cancels.
[controller setCompletionHandler:^(NSString *activityType, BOOL completed) {
if (completed) {
CWStatusBarNotification *notification = [CWStatusBarNotification new];
[notification displayNotificationWithMessage:#"✓ Successfully Shared Centre!"
forDuration:3.0f];
notification.notificationLabelBackgroundColor = [UIColor colorWithRed:38.0f/255.0f green:81.0f/255.0f blue:123.0f/255.0f alpha:1.0f];
notification.notificationLabelTextColor = [UIColor whiteColor];
}
}];
SWIFT 2.0, iOS 8.0 >, you should use completion handler like this:
self.presentViewController(activityVC, animated: true, completion: nil)
activityVC.completionWithItemsHandler = {(activityType, completed:Bool, returnedItems:[AnyObject]?, error: NSError?) in
//do some action
}
see my answer here: https://stackoverflow.com/a/34581940/1109892
Swift 3
func completionHandler(activityType: UIActivityType?, shared: Bool, items: [Any]?, error: Error?) {
if (shared) {
print("Cool user shared some stuff")
}
else {
print("Bad user canceled sharing :(")
}
}
activityController.completionWithItemsHandler = completionHandler

Resources