'Unable to present `LPLinkView` metadata after selecting Messages in UIActivityViewController

I am trying to customize a link preview when a user texts a link to an article in my news aggregator, which is built in SwiftUI.

I am fetching the thumbnail image from the publisher's website using LPMetadataProvider and then using that image to create my own LPLinkMetadata object with other metadata I am providing it. I.e. "show the New York Times' article image thumbnail, but deep link the user to the article in my app when they tap the link preview in their Messages app".

I am able to either provide a preview without the image, which deep links to my app, or the image itself, without a deep link. How can I get both?

public class LinkPresentationItemSource: NSObject, UIActivityItemSource {

    public var metadata: LPLinkMetadata?
    public var articleID: String
    public var title: String
    public var imageUrl: String

    enum Constant {
        static let deepLinkURLSchemeAndHost = "https://www.somedeeplinkurl.com/"
    }

    private func createDeepLinkURLFrom(id: String?) -> String {
        guard let selectedArticleID = id else {
            return ""
        }
        return Constant.deepLinkURLSchemeAndHost + selectedArticleID
    }

    // Prepare data to share
    public func activityViewControllerLinkMetadata(
        _ activityViewController: UIActivityViewController) -> LPLinkMetadata? {

            let lpLinkMetadataProvider = LPMetadataProvider()
            let lpLinkMetadata = LPLinkMetadata()

            guard let imageUrl = URL(string: imageUrl) else {
                return nil
            }
            lpLinkMetadataProvider.startFetchingMetadata(for: imageUrl) { metadata, _ in
                guard let metadata = metadata else {
                    return
                }
                DispatchQueue.main.async {
                    lpLinkMetadata.imageProvider = NSItemProvider(contentsOf: metadata.url)
                }
            }

            guard let originalURL = URL(string: createDeepLinkURLFrom(id: articleID)) else {
                return nil
            }
            lpLinkMetadata.originalURL = originalURL
            lpLinkMetadata.url = lpLinkMetadata.originalURL
            lpLinkMetadata.title = title

            metadata = lpLinkMetadata

            return lpLinkMetadata
    }

    // Placeholder for real data, we don't care in this example so just return a simple string
    public func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
        return "Placeholder"
    }

    /// Return the data will be shared
    /// - Parameters:
    ///   - activityType: Ex: mail, message, airdrop, etc..
    public func activityViewController(_ activityViewController: UIActivityViewController,
                                       itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
        guard let metadata = metadata else {
            return nil
        }

        return metadata.url
    }

    public init(articleID: String, imageUrl: String, title: String) {
        self.articleID = articleID
        self.imageUrl = imageUrl
        self.title = title
    }
}

Specifically what is being returned in the method below seems to not include all the metadata I've provided. If I return metadata or LPLinkPreview(metadata: metadata) the Messages app is not populated with any link preview at all:

public func activityViewController(_ activityViewController: UIActivityViewController,
                                       itemForActivityType activityType: UIActivity.ActivityType?) -> Any?


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source