4

There is a extremely similar question asked by the following post: Different data for sharing providers in UIActivityViewController. But my question is different.

I know how to share different different data of the same type with different activities by using itemForActivityType. For example:

- (id) activityViewController:(UIActivityViewController *)activityViewController
          itemForActivityType:(NSString *)activityType
{
    if ( [activityType isEqualToString:UIActivityTypePostToTwitter] )
       return @"This is a #twitter post!";
    if ( [activityType isEqualToString:UIActivityTypePostToFacebook] )
       return @"This is a facebook post!";
    if ( [activityType isEqualToString:UIActivityTypeAirDrop] )
       return @"Airdrop message text";
    else
       return nil;
}

However, my question is: what if I have different kind of data to share with different activities, what should I do?. For example, what if I would like to share:

  • a string on Twitter;
  • a array of an string and and image on Facebook;
  • the actual data of the image (e.g. NSData) with Airdrop.

P.S.:

I also looked at the following protocol function:

- (id)activityViewControllerPlaceholderItem:;

However, I cannot use it because we don't know the value of activityType here.

Community
  • 1
  • 1
Yuchen
  • 30,852
  • 26
  • 164
  • 234
  • "However, in this function, I don't have an access to the activityType." But on the other hand this is only a placeholder. The docs (as opposed to headers, which is what you quote) make it quite clear that you can change types when you get to `itemForActivityType:`. – matt Oct 24 '14 at 16:13
  • @matt, Yeah, you are right. I am actually quoting the description in the header file. But I don't see where it mentioned that we can change the types. Could I please point it out for me? I cannot find it. And also, I have tried, if the return type doesn't match the placeholder type, it won't work. – Yuchen Oct 24 '14 at 16:37
  • https://developer.apple.com/library/ios/documentation/uikit/reference/UIActivityItemSource_protocol/index.html#//apple_ref/occ/intfm/UIActivityItemSource/activityViewControllerPlaceholderItem: – matt Oct 24 '14 at 16:58

2 Answers2

3

You'd want to create and share two or more objects that conform to the UIActivityItemSource, where one returns the String, another one an Image, etc. Then when the delegate callback requesting the item is called you check which activity type was selected (Facebook, Mail, AirDrop, etc) and have one or multiple of the ItemSource's return nil if that item doesn't apply to that activity. Make sure for any chosen activity that at least one of the item's return a non-nil value.

You can take a look at the airdrop sample code to get some examples of how to implement UIActivityItemSource

Axel Guilmin
  • 11,454
  • 9
  • 54
  • 64
ccjensen
  • 4,578
  • 2
  • 23
  • 25
1

For anyone still looking for a solution in objective-c, this is for sharing different datasources, returning more than one object, and it works with whats'app share. In my case I wanted both picture and text for all itemForActivityType:

FIRST: create your UIActivityItemSource, 1 for text, and 1 for the image

MyShareImage.h

    @protocol giveMeImageToShare
    - (UIImage*)imageToShare;
   @end

   @interface MyShareImage : NSObject<UIActivityItemSource>

   @property (weak,nonatomic) id<giveMeImageToShare> delegate;

   @end

MyShareImage.m

  #import "MyShareImage.h"
  @implementation MyShareImage
  - (id)activityViewControllerPlaceholderItem:(UIActivityViewController*)activityViewController{
   return @"";
   }

   - (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(UIActivityType)activityType{
return [[self delegate] imageToShare];
   }

then, MyShareText.h

  @protocol givemetextToShare

   - (NSString*)textToShare;

   @end

   @interface MyShareText : NSObject<UIActivityItemSource>

   @property (weak,nonatomic) id<givemetextToShare> delegate;

   @end

MyShareText.m

  @implementation MyShareText
  - (id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController{
      return @"";
  }

   - (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(UIActivityType)activityType{
       if ([activityType containsString:@"net.whatsapp.WhatsApp.ShareExtension"]) {
          return nil;
       }
       return [[self delegate] textToShare];

}

And now the activityController:

   - (void)shareAllPossible:(id)sender withThisImage:(UIImage*)immagineShare andThisText:(NSString*)testoShare{

       immagine = immagineShare;
       testo = testoShare;
       MyShareText *myShareText = [MyShareText new];
       myShareText.delegate = self;
       MyShareImage *myShareImage = [MyShareImage new];
       myShareImage.delegate = self;
       NSAssert(immagineShare, @"The image must be loaded to share.");
       if (immagineShare) {
           UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:@[myShareImage ,myShareText] applicationActivities:nil];

   activityController.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
        if (completed)
        {
            //NSLog(@"The Activity: %@ was completed", activityType);
                      }
        else {
            //NSLog(@"The Activity: %@ was NOT completed", activityType);
        }

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

}

Hope it helps. * got inspiration from https://stackoverflow.com/a/37548529/1907742 Mchurch

Community
  • 1
  • 1
Mchurch
  • 74
  • 1
  • 8