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

后端 未结 2 533
孤独总比滥情好
孤独总比滥情好 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<Bool>
        fileprivate let viewController = UIViewController()
        fileprivate let documentInteractionController: UIDocumentInteractionController
    
        init(_ isExportingDocument: Binding<Bool>, url: URL) {
            self.isExportingDocument = isExportingDocument
            documentInteractionController = .init(url: url)
        }
    
        func makeUIViewController(context: UIViewControllerRepresentableContext<DocumentInteractionController>) -> UIViewController { viewController }
    
        func updateUIViewController(_ controller: UIViewController, context: UIViewControllerRepresentableContext<DocumentInteractionController>) {
            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

    0 讨论(0)
  • 2021-01-25 02:21

    I used UIActivityViewController to save a file on my phone. It's simple and works.

    import SwiftUI
    
    struct ContentView: View {
    
        var body: some View {
            Button(action: wirtieFile) {
                Image(systemName: "square.and.arrow.up")
            }
        }
    
        func wirtieFile() -> Void{
            let file = "test.txt"
            let dir = NSURL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(file)
            let contents = "test..."
            do {
               try contents.write(to: dir!, atomically: true, encoding: .utf8)
            } catch {
               print(error.localizedDescription)
            }
            var filesToShare = [Any]()
            filesToShare.append(dir!)
            let av = UIActivityViewController(activityItems: filesToShare, applicationActivities: nil)
            UIApplication.shared.windows.first?.rootViewController?.present(av, animated: true, completion: nil)
        }
    }
    
    0 讨论(0)
提交回复
热议问题