Share multiple Transferables with ShareLink

I am trying to use a ShareLink to share multiple transferrable, and I cannot work out which of the initialisers to use - none seem to work.

Assuming I have a transferable that takes some data and processes it asynchronously:

struct MyTransferable: some Transferable {
    let renderer: Renderer

	static var transferRepresentation: some TransferRepresentation {
		DataRepresentation(exportedContentType: .png) { transferable in
			let image = try await transferable.render.render()
			return image
		}
	}
}

In SwiftUI, I want to share N of these transferables. For example:

struct MyView: View {
    private var transferables: [any Transferable] {
        [MyTransferable(), MyTransferable()]
    }

    var body: some View {
        ShareLink("Renders", items: transferables)
    }
}

But the compiler doesn't like this - it complains with "No exact matches in call to initializer".

Is this possible? I feel like it should be?

Answered by aronskaya in 778386022
Accepted Answer

Ah, thank you @aronskaya. That works.

It was a bit of a challenge to work out exactly what the compiler wanted, but for reference something like this:

/// A transferable that generates the image to be shared asynchronously. A preview
/// message, image and icon are provided here so they can be used to populate the
/// sharing UI, but they should not be generated asynchronously. 
///
struct MyTransferable: some Transferable {
    let renderer: Renderer

    var message: String {
        // TODO: Provide a real message string here.
        //
        return "Render"
    }

    var previewImage: Image {
        // TODO: Provide a real preview image here.
        //
        return Image("previewImage")
    }

    var previewIcon: Image {
        // TODO: Provide a real preview icon here.
        //
        return Image("previewIcon")
    }

    static var transferRepresentation: some TransferRepresentation {
        DataRepresentation(exportedContentType: .png) { transferable in
            return try await transferable.renderer.render()
        }
    }
}

/// A view for testing the sharing link.
///
struct MyView: View {
    private var transferables: [MyTransferable] {
        [MyTransferable(), MyTransferable()]
    }

    var body: some View {
        ShareLink<[MyTransferable], Image, Image, DefaultShareLinkLabel>(items: transferables { transferable in
	        SharePreview(transferable.message, image: transferable.previewImage, icon: transferable.previewIcon)
        }
    }
}

Thanks again

Hi Matt,

when I try to use your solution

struct MyTransferable: some Transferable {

the compiler chokes on the "some" keyword:

'some' types are only permitted in properties, subscripts, and functions

How did you get this to compile?

Thanks, Marc

Share multiple Transferables with ShareLink
 
 
Q