// // SaveDocumentPicker.swift // Browse // // Created by Javier Cicchelli on 17/12/2022. // Copyright © 2022 Röck+Cöde. All rights reserved. // import Foundation import SwiftUI import UIKit struct SaveDocumentPicker: UIViewControllerRepresentable { // MARK: Type aliases typealias DownloadedClosure = (NSError?) -> Void typealias CancelledClosure = () -> Void // MARK: Properties private let fileName: String private let fileData: Data private let downloaded: DownloadedClosure private let cancelled: CancelledClosure? // MARK: Initialisers init( fileName: String, fileData: Data, downloaded: @escaping DownloadedClosure, cancelled: CancelledClosure? = nil ) { self.fileName = fileName self.fileData = fileData self.downloaded = downloaded self.cancelled = cancelled } // MARK: Functions func makeUIViewController(context: Context) -> UIDocumentPickerViewController { let controller = UIDocumentPickerViewController( forOpeningContentTypes: [.folder] ) controller.allowsMultipleSelection = false controller.shouldShowFileExtensions = false controller.delegate = context.coordinator return controller } func updateUIViewController( _ uiViewController: UIDocumentPickerViewController, context: Context ) { } func makeCoordinator() -> Coordinator { .init(self) } } // MARK: - Coordinators extension SaveDocumentPicker { class Coordinator: NSObject, UIDocumentPickerDelegate { // MARK: Properties private let parent: SaveDocumentPicker private let fileCoordinator: NSFileCoordinator = .init() private let fileManager: FileManager = .default // MARK: Initialisers init(_ parent: SaveDocumentPicker) { self.parent = parent } // MARK: UIDocumentPickerDelegate func documentPicker( _ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL] ) { guard let url = urls.first, url.startAccessingSecurityScopedResource() else { // TODO: Handle this error appropriately. return } var error: NSError? fileCoordinator.coordinate( writingItemAt: url, error: &error ) { url in fileManager.createFile( atPath: url.appendingPathComponent(parent.fileName).relativePath, contents: parent.fileData ) } url.stopAccessingSecurityScopedResource() parent.downloaded(error) } func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) { controller.dismiss(animated: true) { [weak self] in self?.parent.cancelled?() } } } }