UIActivityViewController - Email and Twitter sharing
Asked Answered
P

5

35

I recently started working with UIActivity to share my app to the world, but I have few problems. First, I didn't find how to set the subject of my email. Is there any way? Second, when I set the body text of my email, there is a extra "enter" (first line of the email is blank and my text starts at the second line). Here's the code:

 NSMutableArray *array = [[NSMutableArray alloc] initWithObjects: @"Test", nil];

    UIActivityViewController *activityViewController = [[UIActivityViewController alloc]
                                   initWithActivityItems:array applicationActivities:nil];

And in the email, it shows that:

"

Test "

Third: is there a way to know which sharing method has been selected? Because I want to include a hashtag in my post when the user shares on twitter, but now it gets integrated in the email also, which obviously doesn't make sense.

Thanks!

Phyletic answered 20/10, 2012 at 1:14 Comment(0)
A
50

For adding subject to the email using UIActivityViewController on iOS6, this is the best solution that anyone can use.. All you have to do is call the following while initializing UIActivityViewController.

UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:applicationActivities];
[activityViewController setValue:@"My Subject Text" forKey:@"subject"];

And your UIActivityViewController is populated with a subject.

Aarau answered 28/6, 2013 at 16:41 Comment(7)
is there any other key that can be passed into UIActivityViewController?Jubal
I guess you can use the following: (UIActivity *)activity, (NSArray *) activityItems, (NSArray *) applicationActivities, (NSArray *) excludedActivityTypes, (NSString *) subject, (int) totalProviderCount, (BOOL) useBlackPopoverStyle.Aarau
Is this legal?? It's not documented.Cockerel
@Aarau Is it possible to set value for Twitter and Facebook based on keys like this one? Like if it was for Twitter use this short text with hashtags and mentions but if it was for FB use the longer version?Nonego
@Nonego I haven't tried anything like that but I guess that should work as long as the classes have those variables defined.Aarau
If you decide to use this please check if you're running on iOS 6 first. If not, use the new UIActivityItemSource protocol method to set the subject.Kaye
How can I add a image ?Rasure
T
24

In iOS7, this is possible by using -

activityViewController:subjectForActivityType:

When posting an item the service may provide for a separate subject field and data field, such as an email message. Implement this method if you wish to provide a subject field for services that support one.

Check - https://developer.apple.com/library/ios/documentation/uikit/reference/UIActivityItemSource_protocol/Reference/Reference.html#//apple_ref/occ/intfm/UIActivityItemSource/activityViewController:subjectForActivityType:

Tomkin answered 8/10, 2013 at 15:12 Comment(0)
C
16

1 and 2: How do I set recipients for UIActivityViewController in iOS 6?

Although both provided methods are a bit of a hack, especially the first one, it is possible.

3: it is possible to share different content on different services, but the number of items and their types should be the same (but it is not a limitation, really, as you can return nil for items you don't need on particular service). You have to create sharing items after the service was selected using UIActivityItemSource protocol

Code I use:

Show UIActivityViewController with the current controller as provider of all items (it should have in .h file):

const int numberOfSharedItems = 5;

- (IBAction)shareAction:(id)sender
{
    NSMutableArray *shareItems = [NSMutableArray new];
        while ([shareItems count] < numberOfSharedItems)
            [shareItems addObject: self];

        UIActivityViewController *shareController =
            [[UIActivityViewController alloc]
                // actual items are prepared by UIActivityItemSource protocol methods below
                initWithActivityItems: shareItems
                applicationActivities :nil];

        shareController.excludedActivityTypes = @[UIActivityTypeMessage, UIActivityTypePrint, UIActivityTypeCopyToPasteboard, UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll];

        [self presentViewController: shareController animated: YES completion: nil];
}

Make placeholders for items that will be shared:

-(id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController
{
    static UIActivityViewController *shareController;
    static int itemNo;
    if (shareController == activityViewController && itemNo < numberOfSharedItems - 1)
        itemNo++;
    else {
        itemNo = 0;
        shareController = activityViewController;
    }

    switch (itemNo) {
        case 0: return @""; // intro in email
        case 1: return @""; // email text
        case 2: return [NSURL new]; // link
        case 3: return [UIImage new]; // picture
        case 4: return @""; // extra text (via in twitter, signature in email)
        default: return nil;
    }
}

Make actual items that will be shared, differently for different services:

-(id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType
{
    // the number of item to share
    static UIActivityViewController *shareController;
    static int itemNo;
    if (shareController == activityViewController && itemNo < numberOfSharedItems - 1)
        itemNo++;
    else {
        itemNo = 0;
        shareController = activityViewController;
    }

    NSString *shareText = [self shareText]; // whatever you fancy
    NSURL *shareURL = [self shareURL];

    // twitter
    if ([activityType isEqualToString: UIActivityTypePostToTwitter])
        switch (itemNo) {
            case 0: return nil;
            case 1: return shareText; // you can change text for twitter, I add $ to stock symbol inside shareText here, e.g. Hashtags can be added too
            case 2: return shareURL;
            case 3: return nil; // no picture
            case 4: return @"via @YourApp";
            default: return nil;
        }

    // email
    else if ([activityType isEqualToString: UIActivityTypeMail])
        switch (itemNo) {
            case 0: return @"Hi!\r\n\r\nI used YourApp\r\n";
            case 1: return shareText;
            case 2: return shareURL;
            case 3: return nil; // no picture
            case 4: return [@"\r\nCheck it out.\r\n\r\nCheers\r\n" stringByAppendingString: [self userName]];
            default: return nil;
        }

    else // Facebook or something else in the future
        switch (itemNo) {
            case 0: return nil;
            case 1: return shareText;
            case 2: return shareURL;
            case 3: return [self shareImage];
            case 4: return nil;
            default: return nil;
        }
}
Callosity answered 2/6, 2013 at 22:51 Comment(4)
this answer is useful as an example of how the UIActivityItemSource protocol works and can be put to use for different activity types, but i would not suggest using it as-is - the dependency on the itemNo and the order that these methods are called by internal UIActivityViewController code is baked in... in a scary way. a bit of a recipe to break downstream if they happen to change the way they call you.Parisparish
Can you clarify how you use this?? I want to include an image / text /url etc for Facebook. Can I just use MYNActivityProvider *provider0 = [[MYNActivityProvider alloc]init]; UIActivityViewController *vc = [[UIActivityViewController alloc] initWithActivityItems:@[provider0] applicationActivities:nil]; - when I try this - it only returns the first text item / no image for facebook / twitter.Pahang
@Pahang sorry, it's been quite some time... it seems like you may have some newer api than I had at the timeCallosity
@Callosity your answer is the best documentation I've found on the subject so far! just on a side note, in FB i get an extra call to itemForActivityType if I return the URL it works fine..Tropicalize
R
2

u can simply create a class as follows :

 @interface MYNActivityProvider : UIActivityItemProvider <UIActivityItemSource>

 @end

// implementation

 - (id) activityViewController:(UIActivityViewController *)activityViewController
      itemForActivityType:(NSString *)activityType
 { 
    if ( [activityType isEqualToString:UIActivityTypePostToTwitter] ) {
        return stringToPost;
     }
    if ( [activityType isEqualToString:UIActivityTypePostToFacebook] ) {
         return stringToPost;
    }
    if ( [activityType isEqualToString:UIActivityTypeMessage] ) {
        return @"SMS message text";  
    }
    if ( [activityType isEqualToString:UIActivityTypeMail] ) {
        return @"Email text here!";
    }
    if ( [activityType isEqualToString:@"Custom"] ) {
        return @"app custom text";
    }
    return nil;
 }
Reggiereggis answered 23/7, 2014 at 7:54 Comment(0)
C
0

You might want to try OvershareKit.

We are frequently asked why someone would use OvershareKit instead of UIActivityViewController (UIAVC) and UIActivity. UIAVC is great for apps that know they’ll never have a need for any of the following:

  1. Never need to integrate with more than one or two third party services.
  2. Never need to tweak the UI for the activity sheet and sharing screens.
  3. Never care to provide separate, media-specific content for each sharing type (email versus SMS, etc.)
  4. Never need to have multiple items such as a Copy Text versus a Copy Link in the same sheet.
  5. Don't mind that all non-system-provided activities get stuck with boring monochromatic icons.

Your situation is (3) - a need to care about different content for different sharing type.

Cordle answered 3/4, 2014 at 3:32 Comment(2)
It's worth mentioning that it's iOS 7 only.Tripedal
This is no loner under active development and does not build for 9+Tipi

© 2022 - 2024 — McMap. All rights reserved.