iOS13 share sheet: how to set preview thumbnail when sharing UIImage

Lobo picture Lobo · Sep 9, 2019 · Viewed 8.7k times · Source

The new share sheet on iOS13 shows a preview/thumbnail of the item being shared on its top left corner.

When sharing an UIImage using an UIActivityViewController I would expect a preview/thumbnail of the image being shared to be displayed there (like e.g. when sharing an image attached to the built in Mail app), but instead the share sheet is showing my app's icon.

What code/settings are required to show a thumbnail of the image being exported in the share sheet?

I have set up the UIActivityViewController as follows:

let image = UIImage(named: "test")!
let activityVC = UIActivityViewController(activityItems: [image], applicationActivities: nil)                          
activityVC.popoverPresentationController?.sourceView = self.view                            
self.present(activityVC, animated: true, completion: nil)

Answer

denkeni picture denkeni · Feb 20, 2020

The simplest code I've implemented to share a UIImage with better user experience:

  1. Import the LinkPresentation framework:
#import <LinkPresentation/LPLinkMetadata.h>  // for Obj-C

import LinkPresentation  // for Swift, below
  1. Present the UIActivityViewController in the UIViewController, with [image, self]:
let image = UIImage(named: "YourImage")!
let share = UIActivityViewController(activityItems: [image, self], applicationActivities: nil)
present(share, animated: true, completion: nil)
  1. Make the UIViewController conform to UIActivityItemSource:
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
    return ""
}

func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
    return nil
}

func activityViewControllerLinkMetadata(_ activityViewController: UIActivityViewController) -> LPLinkMetadata? {
    let image = UIImage(named: "YourImage")!
    let imageProvider = NSItemProvider(object: image)
    let metadata = LPLinkMetadata()
    metadata.imageProvider = imageProvider
    return metadata
}

Because UIImage has already conformed to NSItemProviderWriting, just serve it for NSItemProvider.

Since it's sharing a UIImage, any URL shouldn't be expected. Otherwise user may get URL sharing, rather than image sharing experience.

To accelerate the share sheet preview, feed LPLinkMetadata object with existing resources. No need to fetch it online again. Check the WWDC19 Tech Talks video What's New in Sharing for more details.