How can I write a file in a folder located at Apple's Files App in SwiftUI?

后端 未结 2 537
孤独总比滥情好
孤独总比滥情好 2021-01-25 01:30

I followed the Swift project UsingFiles github and its video to write files in my SwiftUI project. The project UsingFiles can write files to Files APP and then the writing files

2条回答
  •  长情又很酷
    2021-01-25 02:16

    As I have already posted in comments you can NOT programmatically save a file out of your APP Bundle. You can use a UIDocumentInteractionController and ask the user to choose the location where the file is supposed to be written.

    So if you are working with SwiftUI this gets a bit more complicated than the regular Storyboard approach as you can see in this post because you need to implement UIViewControllerRepresentable for UIDocumentInteractionController:


    struct DocumentInteractionController: UIViewControllerRepresentable {
    
        fileprivate var isExportingDocument: Binding
        fileprivate let viewController = UIViewController()
        fileprivate let documentInteractionController: UIDocumentInteractionController
    
        init(_ isExportingDocument: Binding, url: URL) {
            self.isExportingDocument = isExportingDocument
            documentInteractionController = .init(url: url)
        }
    
        func makeUIViewController(context: UIViewControllerRepresentableContext) -> UIViewController { viewController }
    
        func updateUIViewController(_ controller: UIViewController, context: UIViewControllerRepresentableContext) {
            if isExportingDocument.wrappedValue && documentInteractionController.delegate == nil {
                documentInteractionController.uti = documentInteractionController.url?.typeIdentifier ?? "public.data, public.content"
                documentInteractionController.name = documentInteractionController.url?.localizedName
                documentInteractionController.presentOptionsMenu(from: controller.view.frame, in: controller.view, animated: true)
                documentInteractionController.delegate = context.coordinator
                documentInteractionController.presentPreview(animated: true)
            }
        }
    
        func makeCoordinator() -> Coordintor { .init(self) }
    }
    

    And its Coordinator:

    class Coordintor: NSObject, UIDocumentInteractionControllerDelegate {
        let documentInteractionController: DocumentInteractionController
        init(_ controller: DocumentInteractionController) {
            documentInteractionController = controller
        }
        func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController { documentInteractionController.viewController }
    
        func documentInteractionControllerDidDismissOptionsMenu(_ controller: UIDocumentInteractionController) {
            controller.delegate = nil
            documentInteractionController.isExportingDocument.wrappedValue = false
        }
    }
    

    Now you can create your DocumentInteraction View and its previews:

    struct DocumentInteraction: View {
        @State private var isExportingDocument = false
        var body: some View {
            VStack {
                Button("Export Document") { self.isExportingDocument = true }
                .background(DocumentInteractionController($isExportingDocument,
                    url: Bundle.main.url(forResource: "sample", withExtension: "pdf")!))
            }
        }
    }
    
    struct DocumentInteraction_Previews: PreviewProvider {
        static var previews: some View { DocumentInteraction() }
    }
    

    You will need those helpers as well:

    extension URL {
        var typeIdentifier: String? { (try? resourceValues(forKeys: [.typeIdentifierKey]))?.typeIdentifier }
        var localizedName: String? { (try? resourceValues(forKeys: [.localizedNameKey]))?.localizedName }
    }
    

    Sample project

提交回复
热议问题