Share app link to by ActivityViewController iOS swift?

Viewed 22257

My app is not Live yet. I got the app ID from the App Store Connect. I want to share the app link on social media apps. I used the UIActivityViewController:

let string1 = "itms-apps://itunes.apple.com/app/idXXXXXXX"
let url = NSURL(string: string1)

let shareItems = [UIApplication.sharedApplication().openURL(url!)]
    
let activityViewController = UIActivityViewController(activityItems: shareItems, applicationActivities: nil)
self.presentViewController(activityViewController, animated: true, completion: nil)

Problem: It is not showing some social media apps like WhatsApp.

enter image description here

4 Answers

Solution for Swift 4 or better:

This solution also works on iPad (the solution above crashes on iPad):

if let urlStr = NSURL(string: "https://apps.apple.com/us/app/idxxxxxxxx?ls=1&mt=8") {
    let objectsToShare = [urlStr]
    let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)

    if UIDevice.current.userInterfaceIdiom == .pad {
        if let popup = activityVC.popoverPresentationController {
            popup.sourceView = self.view
            popup.sourceRect = CGRect(x: self.view.frame.size.width / 2, y: self.view.frame.size.height / 4, width: 0, height: 0)
        }
    }

    self.present(activityVC, animated: true, completion: nil)
}

The solutions here are all good but it's worth considering implementing the UIActivityItemSource protocol and LinkPresentation framework.

My solution achieves the following:

  • App icon and title showing at the top of the UIActivityViewController
  • Direct link to App Store for AirDrop ActivityType
  • Custom text for messages and emails, including an opportunity to add a link to the app on Google Play if required
  • Subject for emails
  • Doesn't use the LPMetaDataProvider fetch request (as described in this WWDC 2019 262 video) so faster to load

0. Init the UIActivityViewController:

Set the items to self:

let activityVC = UIActivityViewController(activityItems: [self], applicationActivities: nil)

Exclude certain ActivityTypes which don't apply:

activityVC.excludedActivityTypes = [.addToReadingList, .assignToContact, .markupAsPDF, .openInIBooks, .saveToCameraRoll]

For iPad set the popoverPresentationController.sourceView or .barButtonItem (this is ignored on iPhone):

activityVC.popoverPresentationController?.sourceView = myButton

Present it:

present(activityVC, animated: true, completion: nil)

1. Implement the required UIActivityItemSource methods

https://developer.apple.com/documentation/uikit/uiactivityitemsource

You must implement the placeholder method which according to the docs:

Placeholder objects do not have to contain any real data but should be configured as closely as possible to the actual data object you intend to provide.

func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
    return ""
}

And the actual data, returning a link to the app for AirDrop and text for everything else:

func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
    
    if activityType == .airDrop {
        return URL(string: "APP_STORE_URL")!
    }
    
    return "Check out the APP_NAME on the App Store: APP_STORE_URL or on the Google Play Store: PLAY_STORE_URL"
}

2. Implement the subject method

From the docs:

For activities that support a subject field, returns the subject for the item.

func activityViewController(_ activityViewController: UIActivityViewController, subjectForActivityType activityType: UIActivity.ActivityType?) -> String {
    return "EMAIL_SUBJECT" // e.g. App name
}

3. Implement the LPLinkMetaData method

From the docs:

Returns metadata to display in the preview header of the share sheet.

@available(iOS 13.0, *)
func activityViewControllerLinkMetadata(_ activityViewController: UIActivityViewController) -> LPLinkMetadata? {
    let metadata = LPLinkMetadata()
    metadata.title = "APP_NAME"
    return metadata
}

iPhone solution for Swift 5+

let url = URL(string: "https://apps.apple.com/us/app/id1535629801")!
let vc = UIActivityViewController(activityItems: [url], applicationActivities: nil)
present(vc, animated: true)
Related