Implemented the SaveDocumentPicker component for the Browse module.

This commit is contained in:
Javier Cicchelli 2022-12-18 01:03:32 +01:00
parent 7d737cb12b
commit 76a2fa89fb

View File

@ -0,0 +1,120 @@
//
// 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?()
}
}
}
}