2
votes

I am using UIActivityViewController to share text, a screenshot and a URL. It works fine for Twitter, email, SMS etc. In fact everything except Facebook.

As I understand it, Facebook no longer allows pre-filled text to be shared, so I expect just the screenshot and URL to be shared. But when the user selects Facebook, the image that appears is an image taken directly from the URL instead of the image I specify (ie the screenshot). Here is a screenshot of what happens when I use www.google.com as the URL.

If I don't include a URL, then the screenshot appears just fine, but in effect it is just sharing a photo (which is how it appears on Facebook, saying "John Doe added a new photo" and then my screenshot is shown). This all happens whether I'm logged into the Facebook app or not.

Here is my code:

@IBAction func shareButton(sender: AnyObject) {
  // Get screenshot
  UIGraphicsBeginImageContextWithOptions(UIScreen.mainScreen().bounds.size, false, 0)
  self.view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
  let screenshot:UIImage = UIGraphicsGetImageFromCurrentImageContext()
  UIGraphicsEndImageContext()

  let textToShare = "My text here"
  let myWebsite = NSURL(string: "http://www.example.com/")

  socialShare(sharingText: textToShare, sharingImage: screenshot, sharingURL: myWebsite)
}

And then:

func socialShare(sharingText sharingText: String?, sharingImage: UIImage?, sharingURL: NSURL?) {
  var sharingItems = [AnyObject]()

  if let text = sharingText {
    sharingItems.append(text)
  }

  if let image = sharingImage {
    sharingItems.append(image)
  }

  if let url = sharingURL {
    sharingItems.append(url)
  }

  let activityViewController = UIActivityViewController(activityItems: sharingItems, applicationActivities: nil)

  // Excluded sharing options
  activityViewController.excludedActivityTypes = [UIActivityTypeCopyToPasteboard,UIActivityTypeAirDrop,UIActivityTypeAddToReadingList,UIActivityTypeAssignToContact,UIActivityTypePostToTencentWeibo,UIActivityTypePostToVimeo,UIActivityTypePrint,UIActivityTypePostToWeibo]

  // The popover needs additional code to work on iPad, so distinguish between iPhone & iPad
  if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.Phone) { // If iPhone
    self.presentViewController(activityViewController, animated: true, completion: nil)
  } else { // If iPad
    let popoverCntlr = UIPopoverController(contentViewController: activityViewController)
    popoverCntlr.presentPopoverFromRect(CGRectMake(self.view.frame.size.width - 40, 80, 0, 0), inView: self.view, permittedArrowDirections: UIPopoverArrowDirection.Up, animated: true) // position where the popover appears
  }
}

So does anybody know how to share a screenshot AND a URL via Facebook using UIActivityViewController? I suspect the problem is caused from the Facebook end as everything works fine for Twitter etc, but is there a workaround?

3

3 Answers

0
votes

Facebook disabled ability to share both text and image at the same time.

0
votes

I'm not entirely sure it's from the Facebook side. I'm experiencing exactly the same issue when trying to post a URL and an image. I see the same behavior as you with a device (including your screen shot), but it works perfectly through the Xcode simulator. I haven't found any evidence in the API that Facebook will not accept both a URL and photo simultaneously. It would be helpful if you could verify the same. BTW, my version of Xcode is 7.3

0
votes

I am not sure about screenshot but we can share a URL for sure with Facebook. The better way is to subclass the UIActivityItemProvider and the benefit is we can also track which item (activity) has been tapped. I have pasted my Objective-C code here and it may help you.

- (void)showShareSheetWithShareText:(NSString *)shareText onView:(UIViewController *)parentViewController{

@try {

    if ([shareText length] == 0) {

        shareText = @"Default Text";
    }

    dispatch_async(dispatch_get_main_queue(), ^{

        ActivityItemProvider *activityItem = [[ActivityItemProvider alloc] initWithPlaceholderItem:shareText]; // Sub class of UIActivityItemProvider

        UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:@[shareText, activityItem] applicationActivities:nil];
        NSMutableArray *arrExcludeActivities = [[NSMutableArray alloc] initWithObjects:
                                                UIActivityTypePostToWeibo,
                                                UIActivityTypePrint,
                                                UIActivityTypeCopyToPasteboard,
                                                UIActivityTypeAssignToContact,
                                                UIActivityTypeSaveToCameraRoll,
                                                UIActivityTypeAirDrop,
                                                UIActivityTypeAddToReadingList,
                                                UIActivityTypePostToFlickr,
                                                UIActivityTypePostToVimeo,
                                                UIActivityTypeOpenInIBooks,
                                                UIActivityTypePostToTencentWeibo, nil];
        //            @"com.apple.mobilenotes.SharingExtension",
        //            @"com.apple.reminders.RemindersEditorExtension"

        activityVC.excludedActivityTypes = arrExcludeActivities;

        if ([activityVC respondsToSelector:@selector(completionWithItemsHandler)]) {

            activityVC.completionWithItemsHandler = ^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {

                if (completed) {

                    // Log Events
                }
                else{
                    // Show error
                }
            };
        }
        else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
            // Deprecated in iOS 8.  Safe to hide deprecation warnings as the new completion handler is checked for above
            activityVC.completionHandler = ^(UIActivityType __nullable activityType, BOOL completed){

                // Write code for below iOS 8.
            };
#pragma clang diagnostic pop
        }

        UIViewController *presentingViewController;
        if (parentViewController && parentViewController != nil) {

            presentingViewController = parentViewController;
        }
        else{

            presentingViewController = [[[UIApplication sharedApplication].delegate window] rootViewController];
        }

        if (presentingViewController) {
            // Required for iPad/Universal apps on iOS 8+
            if ([presentingViewController respondsToSelector:@selector(popoverPresentationController)]) {
                activityVC.popoverPresentationController.sourceView = presentingViewController.view;
            }

            [presentingViewController presentViewController:activityVC animated:YES completion:nil];
        }
        else {
            NSLog(@"[warning, fatal] No view controller is present to show the share sheet. Aborting.");
        }
    });
}
@catch (NSException *exception) {

    // Catch Exception
 }
}

Now your UIActivityItemProvider subclass of .h header file

@interface ActivityItemProvider : UIActivityItemProvider

@end

and .m implementation file

@implementation ActivityItemProvider

- (id) initWithPlaceholderItem:(id)placeholderItem {

    self = [super initWithPlaceholderItem:placeholderItem];
    return self;
}

- (id)item {

    NSString *channel = [ActivityItemProvider humanReadableChannelWithActivityType:self.activityType];

    NSArray *scrapers = @[@"Facebook", @"Twitter", @"Slack", @"Apple Notes"];
    for (NSString *scraper in scrapers) {

       if ([channel isEqualToString:scraper]) {

           // Do something for these Channels if you want.
    }
 }

 return [NSURL URLWithString:@"Your Site URL"]; // return type should be NSURL else the activity does consider as a normal string.
}

+ (NSString *)humanReadableChannelWithActivityType:(NSString *)activityString {

NSString *channel = activityString; //default
NSDictionary *channelMappings = [[NSDictionary alloc] initWithObjectsAndKeys:
                                 @"Facebook", UIActivityTypePostToFacebook,
                                 @"Twitter", UIActivityTypePostToTwitter,
                                 @"Weibo", UIActivityTypePostToWeibo, // May not use.
                                 @"SMS", UIActivityTypeMessage,
                                 @"Email", UIActivityTypeMail,

                                 @"Print", UIActivityTypePrint,
                                 @"Pasteboard", UIActivityTypeCopyToPasteboard,
                                 @"Contact",UIActivityTypeAssignToContact,
                                 @"CameraRoll", UIActivityTypeSaveToCameraRoll,
                                 @"Reading List", UIActivityTypeAddToReadingList,
                                 @"flickr", UIActivityTypePostToFlickr,
                                 @"Vimeo", UIActivityTypePostToVimeo,
                                 @"Tencent Weibo", UIActivityTypePostToTencentWeibo,
                                 @"AirDrop",UIActivityTypeAirDrop,
                                 @"Books",UIActivityTypeOpenInIBooks,

                                 @"Apple Reminders", @"com.apple.reminders.RemindersEditorExtension",
                                 @"Apple Notes", @"com.apple.mobilenotes.SharingExtension",
                                 @"Slack", @"com.tinyspeck.chatlyio.share",
                                 @"WhatsApp", @"net.whatsapp.WhatsApp.ShareExtension",
                                 @"WeChat", @"com.tencent.xin.sharetimeline",
                                 @"LINE", @"jp.naver.line.Share",
                                 @"Pinterest", @"pinterest.ShareExtension",
                                 nil
                                 ];
  // Set to a more human readible string if we can identify it
  if ([channelMappings objectForKey:activityString]) {
    channel = channelMappings[activityString];
  }
  return channel; // [channel uppercaseString];
}

// For email subject
- (NSString *)activityViewController:(UIActivityViewController *)activityViewController subjectForActivityType:(nullable UIActivityType)activityType{

  return @"Your Email Subject";
}

@end