Handling Importing Universal Type Identifiers
Asked Answered
S

1

5

I am working on an app where data (custom structs) can be transfered between instances of the app running on different phones. The app should be able to open Share Sheet and send the data to another device where it will automatically open the app for the data to be imported. (Having support for the share sheet is important because the app needs to be functional when there is not internet access and airdrop seems to be the only way to transfer data between phone when there is no internet.)

So far I have made the struct I would like to transfer between instances of the app conform to the Transferrable Protocol. I have also defined a custom Uniform Type Identifier in the code and the info.plist. With this, I am able to export the struct using the share sheet and it sends a json file ending in .stageresult. However, my issue is that when other devices receive the file they do not open it automatically nor do they give any way to do it manually. Also, I have been unable to find anything online about how to handle importing custom files. Is there a way I can call a function with the imported data to load it into my app? What is the proper way to handle importing custome universal type identifers using Swift/SwiftUI

import UniformTypeIdentifiers
import SwiftUI
import Foundation

extension UTType {
    static var stageresult: UTType { UTType(exportedAs: "com.example.stageresult") }
}

struct StageResult: Codable {
    var name: String
    var start: Bool
    var recordings: [Recording]
}

struct Recording: Codable {
    var plate: String
    var timestamp: Double
}

extension StageResult: Transferable {
    static var transferRepresentation: some TransferRepresentation {
        CodableRepresentation(contentType: .stageresult)
    }
}

Defining Type Identifiers Info.plist Supports Opening Documents In Place

Sophisticated answered 17/2, 2023 at 2:42 Comment(0)
H
3

Not too long ago, I encountered the same issue. Unfortunately, there's not much documentation from Apple on this. After a searching for quite some time, I finally found this tweet by an Apple frameworks engineer, which helped me out.

Users of my application can share recipes with each other using the share sheet feature. The recipients of these recipes can then import them and save them for later use. To facilitate this, I added the .onOpenURL modifier to my main view in order to handle the import of new recipes.

ContentView()
    .environmentObject(recipeData)
    .onOpenURL { url in
        guard url.pathExtension == "smoothierecipe" else {
            print("File does not end with .smoothierecipe extension")
            return
            
        }
        guard let data = try? Data(contentsOf: url) else {
            print("Error reading data from file")
            return
        }

        guard let recipe = try? JSONDecoder().decode(SmoothieRecipe.self, from: data) else {
            print("Unable to decode recipe file")
            return
        }

        recipeData.add(recipe: recipe)
    }
                    

Regarding the automatic opening part of your question; Unfortunately I haven't yet found a solution to that myself. I did, however, discover a workaround. If you can access the share sheet for the saved item (which is possible through the Files app), your application should be among the available options for handling it. Another option is to utilize the new paste button or even the .dropDestination feature with file drag-and-drop.

Edit: You might also check out some of the apple docs on document based apps. This might be what you're looking for.

Hyehyena answered 22/3, 2023 at 5:52 Comment(2)
developer.apple.com/documentation/uikit/view_controllers/… This also may be relevant, but it’s UIKitHyehyena
You need LSSupportsOpeningDocumentsInPlace in your plist. See #69770144Murvyn

© 2022 - 2024 — McMap. All rights reserved.