Search code examples
swiftswiftuiuiactivityviewcontrollerios16

SwiftUI ShareLink share custom data


I am trying to share a custom struct between two users within the App via ShareLink (UIActivityViewController) in SwiftUI. I created a custom Document Type, the Exported Type Identifier and marked the struct as Transferable.

However, while I am able to save the example to a file, I would like to send it to another user via AirDrop or similar, s.t. the App appears as an Application Activity.

import SwiftUI
import UniformTypeIdentifiers

struct SwiftUIView: View {
    @State private var customStruct: CustomStruct = CustomStruct()
    var body: some View {
        ShareLink(item: customStruct, preview: SharePreview(customStruct.name))
    }
}

struct CustomStruct: Codable {
    var name: String = "Test Example"
    var description: String = "Test"
}

extension CustomStruct: Transferable {
    static var transferRepresentation: some TransferRepresentation {
        CodableRepresentation(contentType: .customStruct)
    }
}

extension UTType {
    static var customStruct: UTType { UTType(exportedAs: "com.TestExample.CustomStruct") }
}

struct SwiftUIView_Previews: PreviewProvider {
    static var previews: some View {
        SwiftUIView()
    }
}

The Document Type

The Exported Type Identifier

The result, without share to app option


Solution

  • Have you tried setting the "Conforms To" value in "Exported Type Identifiers" to public.json instead of public.data? After all, your custom struct conforms to Codable and can thus be serialized into JSON. For me this did the trick and Messages started showing up in the share sheet. When running on a device, I also see AirDrop.

    What I’m still struggling with is how the receiving app can actually handle the file. I added the LSSupportsOpeningDocumentsInPlace key to Info.plist and set it to YES which causes the file to open in my app by tapping, but then I’m a bit stuck. Maybe onOpenURL: and decode the JSON file that the URL points to? I found zero results on the internet for this, which is a bit surprising.