ShareLink and DataRepresentation

In my app, I'd like to be able to share a .csv file via ShareLink and Transferable. I watched the "Meet Transferable" WWDC22 video and it should be possible as the presenter demonstrated that use case.

However, when I try this on my end, I am able to share the content but somehow it is treated by iOS as plaintext and when sharing by email or messages, it will just add the text content to the body.

If I try to share via AirDrop, it creates a random filename with the .txt extension even though I specify .commaSeparatedText.

The only way this somewhat works is when saving to files. It will save as a .csv file but the filename is set to "comma-separated values".

Here's some code:

struct MyArchive {
    enum ValidationError: Error {
        case invalid
    }

    var filename: String {
        return "myarchive.csv"
    }
    

    init(csvData: Data) throws {
        //...
    }


    func convertToCSV() throws -> Data {
        let test = "Name,Email\nPete,pete@example.com"
        if let data = test.data(using: .utf8) {
            return data
        }
        else {
            throw ValidationError.invalid
        }
    } 
}

extension MyArchive: Transferable {
    static var transferRepresentation: some TransferRepresentation {
        DataRepresentation(contentType: .commaSeparatedText) { archive in
            try archive.convertToCSV()
        } importing: { data in
            try MyArchive(csvData: data)
        }
    }

}

And in my View:

struct View: View {
   var body: some View {
      //...
      let csv = MyArchive()

      ShareLink(
        item: csv,
        preview: SharePreview(
                        csv.filename,
                        image: Image(systemName: "doc.plaintext")
                    )
     )
   }
}

I'm at the point that I wonder if I'm doing something wrong or this just doesn't work in iOS 16 beta 1.

Any hints?

Thanks!

My I add that using FileRepresentation instead of DataRepresentation has the same effect:

extension FuelUpsArchive: Transferable {
    static var transferRepresentation: some TransferRepresentation {

        FileRepresentation(contentType: .commaSeparatedText) {
            SentTransferredFile($0.file)
        } importing: { received in
            try! self.init(csvData: Data())
        }
    }
}

Try it on iOS (iPad Simulator), try to share it and locally save it to Files locally on the iPad (you don't need iCloud)

If it works then your code is fine, I feel transferable on macOS has a lot of bugs.

After testing and confirming the issue, it would be great if you could file a feedback.

Having the same problem and my code looks virtually identical to yours. In the logs I see the following error:

 [ShareSheet] Couldn't load file URL for Collaboration Item Provider:<NSItemProvider: 0x600003f86840> {types = (

    "public.comma-separated-values-text"

)} : (null)

Wish that the catalog app in the talk was available in the samples so I could test that and compare to what I have.

Any update on this? I have the same issue and is obviously not a beta issue at this point. Thanks.

There is a suggestedFileName func on TransferRepresentation that you can use to provide a default file name, if you just want to avoid the "comma-separated-values" value that Apple defaults to.

    static var transferRepresentation: some TransferRepresentation {
        DataRepresentation(exportedContentType: .csv) { archive in
            try archive.convertToCSV()
        }
        .suggestedFileName("Archived Data.csv")
    }

When you share your object, it should then default to a file name of "Archived Data.csv". Note that this parameter is attached to the static var, so you won't get access to any instance fields within your data to generate a more dynamic file name.

ShareLink and DataRepresentation
 
 
Q