How to use ShareLink with an item from an async function?

581 views Asked by At

I want to use ShareLink to share a URL that is generated from an API call from an async function.

I tried something like this, and it doesn't work:

ShareLink (item: Task {await getSharingURL()} ) 
   { Image(systemName: "square.and.arrow.up") } 

In apple's documentation they say:

Sometimes the content that your app shares isn’t immediately available. You can use FileRepresentation or DataRepresentation when you need an asynchronous operation, like a network request, to retrieve and prepare the content.

https://developer.apple.com/documentation/SwiftUI/ShareLink

But I am not sure how to use it, and would appreciate any example.

1

There are 1 answers

0
AVS On

Here's how I solved it.

I created a shareable model of whatever the object is I want to create a link for. Pass it whatever parameters you need to create the url.

struct ShareableObject {

    ...

    func shareURL() async -> Data? {
        guard let shortURL = fetch() else {
            return "example.com".data(using: .utf8)
        }
        return shortURL.data(using: .utf8)
    }
}

You will need to define the fetch() function.

Then I made it conform to Transferable, specifically using DataRepresentation so that it can be processed asynchronously.

extension ShareableObject: Transferable {
    enum ShareError: Error {
        case failed
    }
    
    static var transferRepresentation: some TransferRepresentation {
        DataRepresentation(exportedContentType: .plainText) { object in
            guard let data = await object.shareURL() else {
                throw ShareError.failed
            }
            return data
        }
    }
}

Then to deploy this, you just place the ShareableObject in a ShareLink...

ShareLink(item: shareableObject()) {
    Label("Share This Thing", systemImage: "square.and.arrow.up")
}

There might be a more succinct abstraction. If so, I'd love to get the feedback for that in comments or in a second answer.