【问题标题】:UIDocument not saving to file despite indicating success尽管指示成功,但 UIDocument 未保存到文件
【发布时间】:2017-08-28 19:32:39
【问题描述】:

我正在尝试使用UIDocument 在 iCloud Drive 中打开、修改和保存文件。当我使用文件位置调用save(to:for:completionHandler:) 并将.forOverwriting 用于UIDocumentSaveOperation 时,它以success = true 的状态完成。但是,iCloud 文件(在桌面和 iOS 文件浏览器中都可以看到)不会更新,并且在重新打开文件时,不会显示更改。我已验证 contents(forType:) 在保存时返回正确的(修改后的)文件内容。

(注意:我已经看过this question,但不是很有帮助????)

以下是相关的代码部分:

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
    }
}

更新: 我真的需要帮助,我已经尝试了我能想到的一切来解决这个问题。您能给我的任何帮助将不胜感激。

【问题讨论】:

  • @matt 抱歉,应该是.forOverwriting。我只是暂时更改了它,看看它是否有所作为(它没有)。
  • 有人可以提供一些建设性的反馈,而不是投反对票吗?我真的需要找到这个问题的答案。
  • 观察UIDocumentStateChanged 通知。在回调中,您是否碰巧收到inConflict 的报告状态?

标签: ios swift save icloud uidocument


【解决方案1】:

初始文件生成的方式对我来说是:

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

然后修改文件再做:

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

完成后。随后对文件的访问由以下人员完成:

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

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

您可能还需要执行以下操作:

    doc.updateChangeCount(.done)

当文件打开时告诉文档有未保存的更改。只需设置这将在几秒钟后导致保存。你甚至不需要关闭来做到这一点。

... 意味着您要么必须嵌套所有这些,要么确保它们之间有足够的时间以完成它们。

【讨论】:

    【解决方案2】:

    除了上述答案之外,另一个原因可能是保存过程中出现错误contents(forType:)无关。

    例如,如果您实现fileAttributesToWrite(to:for:) 并引发错误,那么即使contents(forType:) 返回正确的数据,这也会导致UIDocumentState.savingError

    【讨论】:

      【解决方案3】:

      所以根据

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

      看起来保存功能实际上并不是用于保存文档。我从阅读中的理解是 save 仅用于创建新文档。我了解您正在使用 .forOverwriting 来保存它,但 iCloud 中可能有一些东西不会让完全覆盖发生。

      在你的 doSaveAndClose 方法中尝试调用

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

      本身。您可能需要执行某种类型的 if 查询来检查文件是否存在。如果没有,则调用 .save(),否则调用 .close 函数。似乎无论何时关闭文档都会保存更改。

      【讨论】:

        猜你喜欢
        • 2016-03-04
        • 1970-01-01
        • 1970-01-01
        • 2017-10-23
        • 1970-01-01
        • 2021-12-18
        • 1970-01-01
        • 1970-01-01
        • 2013-02-20
        相关资源
        最近更新 更多