I'm using QLPreviewController
for displaying different kind of documents. All this documents can be edited by returning QLPreviewItemEditingMode.createCopy
or QLPreviewItemEditingMode.updateContents
to previewController(_:editingModeFor:)
instance method of QLPreviewControllerDelegate
.
Everything works as expected when using QLPreviewItemEditingMode.updateContents
. When user edits document previewController(_:didUpdateContentsOf:)
method of QLPreviewControllerDelegate
is getting called and updated content can be accessed with the url that was passed to data source of QLPreviewController
.
Problem begins when I want to use QLPreviewItemEditingMode.createCopy
. When user stops editing document, previewController(_:didSaveEditedCopyOf:at:)
method of QLPreviewControllerDelegate
is getting called with modifiedContentsURL
parameter of type URL
. The first time this method is getting called I read the data from modifiedContentsURL
and I successfully retrieve it. But every other call after the first one gives back url that has no data to retrieve.
Object that conforms to QLPreviewControllerDelegate
protocol looks like this:
final class CustomQLPreviewDelegate: NSObject, QLPreviewControllerDelegate {
var onSave: ( (Data?) -> Void )?
func previewController(_ controller: QLPreviewController, editingModeFor previewItem: QLPreviewItem) -> QLPreviewItemEditingMode {
.createCopy
}
func previewController(_ controller: QLPreviewController, didSaveEditedCopyOf previewItem: QLPreviewItem, at modifiedContentsURL: URL) {
// nil everytime after the first call
let data = try? Data(contentsOf: modifiedContentsURL)
onSave?(data)
}
}
I also inspected edited document in Finder and its edited copy is generated after the first call, then removed after the second call and never created again in subsequent calls.
I just wanna make sure that I'm doing everything correct before reporting this as a bug to Apple.
As suggested from @Leo Dabus I tried to copy the file from modifiedContentsURL
to some other directory. The item was copied the first time and then never again.
Then I tried moving the file from modifiedContentsURL
and this did the trick. File was moved successfully after every call to previewController(_:didSaveEditedCopyOf:at:)
. Here is the reworked code of my CustomQLPreviewDelegate
class:
final class CustomQLPreviewDelegate: NSObject, QLPreviewControllerDelegate {
var onSave: ( (URL) -> Void )?
let directoryUrlForEditedCopies: URL
init(directoryUrlForEditedCopies: URL) {
self.directoryUrlForEditedCopies = directoryUrlForEditedCopies
super.init()
}
func previewController(_ controller: QLPreviewController, editingModeFor previewItem: QLPreviewItem) -> QLPreviewItemEditingMode {
.createCopy
}
func previewController(_ controller: QLPreviewController, didSaveEditedCopyOf previewItem: QLPreviewItem, at modifiedContentsURL: URL) {
// Get the extension of current edited file
let fileExtension = modifiedContentsURL.pathExtension
guard !fileExtension.isEmpty else { return }
// Create destination url for moving the file
let dstUrl = createUrl(withFileExtension: fileExtension)
// Move edited copy from temporary location
// and call onSave closure with destination url
let error = moveEditedCopy(at: modifiedContentsURL, to: dstUrl)
guard error == nil else { return }
onSave?(dstUrl)
}
private func moveEditedCopy(at srcUrl: URL, to dstUrl: URL) -> Error? {
do {
try FileManager.default.moveItem(at: srcUrl, to: dstUrl)
return nil
} catch (let error) {
return error
}
}
func createUrl(withFileExtension fileExtension: String) -> URL {
let randomFileName = UUID().uuidString
return directoryUrlForEditedCopies.appendingPathComponent(randomFileName, isDirectory: false).appendingPathExtension(fileExtension)
}
}