usar readdle para descargar como app ios swift save icloud uidocument

ios - para - documents by readdle



UIDocument no se guarda en el archivo a pesar de indicar el éxito (3)

Estoy intentando abrir, modificar y guardar un archivo en iCloud Drive utilizando UIDocument . Cuando llamo a save(to:for:completionHandler:) con la ubicación del archivo y utilizando .forOverwriting para UIDocumentSaveOperation , se completa con el estado de success = true . Sin embargo, el archivo de iCloud (como se ve en el navegador de escritorio de iOS y en el de escritorio) no se actualiza, y al volver a abrir el archivo, no se muestran los cambios. He verificado que el contents(forType:) devuelve el contenido del archivo correcto (modificado) al guardar.

(Nota: ya he mirado esta pregunta , pero no fue muy útil 😕)

Aquí están las secciones relevantes del código:

MainViewController.swift:

var saveFile: SBDocument? @IBAction func bbiOpen_pressed(_ sender: UIBarButtonItem) { if saveFile == nil { let importMenu = UIDocumentMenuViewController(documentTypes: self.UTIs, in: .import) importMenu.delegate = self importMenu.popoverPresentationController?.barButtonItem = bbiOpen self.present(importMenu, animated: true, completion: nil) } else { willClose() } } func willClose(_ action: UIAlertAction?) { if saveFile!.hasUnsavedChanges { dlgYesNoCancel(self, title: "Save Changes?", message: "Would you like to save the changes to your document before closing?", onYes: doSaveAndClose, onNo: doClose, onCancel: nil) } else { doSaveAndClose(action) } } func doSaveAndClose(_ action: UIAlertAction?) { saveFile?.save(to: saveFileURL!, for: .forOverwriting, completionHandler: { Void in self.saveFile?.close(completionHandler: self.didClose) }) } func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) { saveFile = SBDocument(fileURL: url) saveFile!.open(completionHandler: { success in self.finishOpen(didCompleteSuccessfully: success) }) } func finishOpen(didCompleteSuccessfully result: Bool) { if result { print(saveFile!.localizedName) saveFileURL = saveFile!.fileURL saveFileName = saveFile!.localizedName self.navTitleBar.prompt = saveFileName bbiOpen.title = NSLocalizedString("titleClose", comment: "Close") bbiOpen.style = .plain } else { saveFile = nil } } @IBAction func bbiSave_pressed(_ sender: UIBarButtonItem) { self.saveFile!.save(to: self.saveFileURL!, for: .forOverwriting, completionHandler: self.didSave) } func didSave(_ success: Bool) { guard success else { print("Error saving soundboard file to /(String(describing: saveFileURL))") return } print("File saved successfully") }

SBDocument.swift:

class SBDocument: UIDocument { override var fileType: String? { get { return "com.whitehatenterprises.SoundBoardFX.sbd" } } override var savingFileType: String? { get { return "com.whitehatenterprises.SoundBoardFX.sbd" } } override init(fileURL url: URL) { super.init(fileURL: url) } override func contents(forType typeName: String) throws -> Any { let arr = NSArray(array: SoundEffects) let data: NSData = NSKeyedArchiver.archivedData(withRootObject: arr) as NSData return data } }

Actualización: realmente necesito ayuda con esto, y he intentado todo lo que se me ocurre para solucionarlo. Cualquier ayuda que me puedas dar sería muy apreciada.


Además de las respuestas anteriores, otra causa de esto puede ser que haya un error durante el proceso de guardado no relacionado con el contents(forType:) .

Por ejemplo, si implementas fileAttributesToWrite(to:for:) y fileAttributesToWrite(to:for:) un error, esto puede provocar que UIDocumentState.savingError , aunque el contents(forType:) devuelva los datos correctos.


Así que de acuerdo con

https://developer.apple.com/reference/uikit/uidocument

Parece que la función de guardar no es realmente para guardar un documento. Mi comprensión al leerlo es que guardar es solo para crear un nuevo documento. Entiendo que está utilizando .forOverwriting para simplemente guardar sobre él, pero puede haber algo en iCloud que no permita que se realice la sobrescritura completa.

En su método doSaveAndClose intente llamar

self.saveFile?.close(completionHandler: self.didClose)

por sí mismo. Es posible que tenga que hacer algún tipo de consulta si comprueba si existe el archivo. Si no es así, llame a .save (), o llame a la función .close. Parece que no importa qué cuando el documento se cierra guarda los cambios.


La forma en que la generación de archivos inicial funciona para mí es:

let doc = YourUIDocumentClass(fileURL: fileURL) doc.save(to: fileURL, for: .forCreating) { success in ... }

Luego modifica el archivo y luego haz:

doc.save(to: fileURL, for: .forOverwriting) { success in ... }

cuando termine. Y los accesos posteriores al archivo se realizan mediante:

doc.open() { success in ... } doc.close() { success in ... }

También es posible que necesites hacer una

doc.updateChangeCount(.done)

Mientras el archivo está abierto para indicar al documento que hay cambios no guardados. Simplemente configurando esto se guardará después de unos segundos. Ni siquiera necesitas el cierre para hacer eso.

El ... significa que debe anidar todo esto o asegurarse de que haya suficiente tiempo entre ellos para que se completen.