2

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

Nimbahus
  • 477
  • 3
  • 16

1 Answers1

1

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.

Martin
  • 145
  • 7
  • I tried it with public.json as well, but it seemed to be a bug with XCode on which I had to set Opening Documents In Place again and restart my Mac and now it shows me Airdrop. However, I am struggling with the second part as well. I believe there is no way with the current API and we have to manually create SceneDelegate. – Nimbahus Jan 05 '23 at 16:27
  • 1
    Yeah, I also had some issues with Xcode not saving the `Info.plist` changes correctly on the first try. On the positive side, I got confirmation from a SwiftUI engineer that `onOpenURL` is indeed the way to go: https://twitter.com/richeterre/status/1610761924676882438 So once you do that and it gets called (which works for me after meticulously defining the UTType and document type), you get a file URL which you can call `.startAccessingSecurityScopedResource()` on, then convert to data using `Data(contentsOf: jsonURL)` and decode it normally using `JSONDecoder`. – Martin Jan 05 '23 at 22:11
  • @Martin Have you managed to make this work? I can send my CodableRepresentation through Messages, but I can't open this JSON back in my app. Here is my plist: LSSupportsOpeningDocumentsInPlaceUTExportedTypeDeclarationsUTTypeConformsTopublic.jsonUTTypeDescriptionConfigurationUTTypeIconFilesUTTypeIdentifiercom.myapp.configurationUTTypeTagSpecification – habibiboss Jan 26 '23 at 22:28
  • @habibiboss Did you remember to define a Document Type (see screenshot in the original question) as well? The Handler Rank should be set to Owner and the type needs to match your UTTypeIdentifier. – Martin Jan 28 '23 at 22:12
  • Thanks @Martin I was able to make it work. However when I share the file on Apple Message, I'm unable to open it, or show the bottom sheet for more options. It's only the case for this app, works fine with emails. I have LSSupportsOpeningDocumentsInPlace set to true in my plist. Is that a normal behaviour for Messages? – habibiboss Feb 20 '23 at 12:28
  • I ran into the exact same issue, please let me know if you figure it out somehow! Tapping the shared file in the iMessage chat simply does nothing for me. It works with email, iCloud Drive… – Martin Feb 23 '23 at 09:36
  • Update: I just found this and it worked for me: https://stackoverflow.com/a/51699268/8538539 A bit clunky, but I guess it does the job :) – Martin Feb 23 '23 at 10:35