Sharing an audio using ShareLink

62 Views Asked by At

Does anyone know how we can share a track(I have the URL, but I will download it, so consider I have the Data the I got from URL session) using ShareLink in Swift, that also has an image attached to it(I believe music apps use GIF sometimes)? Any example is highly appreciated. I cannot find any that shows how we can share an image/video alongside an audio file using share link. I want to share it to instagram stories so it can be played there.

I managed to fetch the Data and download an mp3, but I cannot share it with an image, and even when I try to share the mp3 alone, and click on share it fails. I want the effect of how we share a track from Spotify or other music apps there, which has an image/gif attached to it as well.

A good example of what I am looking for is Spotify or any other music app, you can share a track with an image as its background. How can I achieve that in Swift?

I just want an example to see the process and how it works. Thanks!

Here is a quick mock that I made, I am not using good networking calls or programming principles, just quickly made up something to make it more clear what I am looking for:

public struct Audio: Transferable {
    /*
     I already have the image in my asset, and I fetched the mp3 from my network call, how can I share them both so they work like music apps
     */
    public static var transferRepresentation: some TransferRepresentation {
        DataRepresentation(exportedContentType: .mp3) { audio in
            audio.data
        }
    }


    public var data: Data
}

class GetData {
    var cancellables = Set<AnyCancellable>()
    
    func fetch(_ url: URL) -> AnyPublisher<Data, Error> {
        return URLSession.shared.dataTaskPublisher(for: url)
            .retry(1)
            .tryMap { data, response in
                guard let httpResponse = response as? HTTPURLResponse,
                      (200...299).contains(httpResponse.statusCode) else {
                    throw URLError(.badServerResponse) // or any other appropriate error
                }
                return data
            }
            .eraseToAnyPublisher()
    }
    
    func getData(completion: @escaping (Result<Data, Error>) -> Void) {
        fetch(URL(string: "https://samplelib.com/lib/preview/mp3/sample-3s.mp3")!)
            .sink(receiveCompletion: { completion in
                switch completion {
                case .finished:
                    print("Request completed successfully.")
                case .failure(let error):
                    print("Request failed with error: \(error)")
                }
            }, receiveValue: { data in
                // Handle the received data
                print("Received data: \(data)")
                completion(.success(data))
            })
            .store(in: &cancellables)
    }
}

public struct ShareView: View {
    @State var data = GetData()
    @State var mp3Data: Data? = nil
    public var body: some View {
        VStack {
            Button("Fetch Data") {
                data.getData { result in
                    switch result {
                    case .success(let data):
                        // Handle the received data
                        print("Received data: \(data)")
                        mp3Data = data
                    case .failure(let error):
                        // Handle the error
                        print("Error: \(error)")
                    }
                }
            }
            .padding()
            
            if let mp3Data {
                let audio = Audio(data: mp3Data)
                ShareLink("share me", item: audio, subject: Text("subject"), message: Text("message"), preview: SharePreview("preview"))
            }
        }
    }
}
1

There are 1 best solutions below

0
On

Something like this could work.

  • Add file.mp3 to your project.
  • Add "preview" file to your asset catalog
  • Run following code.
import SwiftUI

struct Audio: Transferable {
    let title: String
    let description: String
    let previewImageName: String
    let audioUrl: URL
    static var transferRepresentation: some TransferRepresentation {
        ProxyRepresentation(exporting: \.audioUrl)
    }
}

struct ContentView: View {
    let audio = Audio(title: "Cool audio", description: "Save this audio", previewImageName: "preview", audioUrl: Bundle.main.url(forResource: "file", withExtension: "mp3")!)
    
    var body: some View {
        VStack {
            ShareLink(
                item: audio,
                preview: SharePreview( audio.title, image: Image(audio.previewImageName, label: Text(audio.description))))
        }
        .padding()
    }
}