79391197

Date: 2025-01-27 14:52:39
Score: 0.5
Natty:
Report link

Well, this trick with the UndoManager worked for me on some Views; on others ist didn't. I was getting tired to spend hours in investigating why this was so. So I was looking for a way to save the document’s content explicitly. This is what I came up with.

In my app the document’s content is encoded as a PropertyList. So why not writing this PropertyList by myself? In MyDocument I create my model and keep a reference on it. In my model I store the fileURL of my document’s file on creating or opening a document:

@main
struct MyApp: App {
    var body: some Scene {
        DocumentGroup(newDocument: MyDocument()) { file in
            ContentView(document: file.$document)
                .environmentObject(file.document.model)
                .task {
                    file.document.model.fileURL = file.fileURL
               }
         }
    }
}

So I can access this URL in my model:

func save() {
    if let url = fileURL {                                                  // we know our url
        if url.startAccessingSecurityScopedResource() {                     // access file outside sandbox
            if let outStream = OutputStream(url: url, append: false),       // create the output stream
               let data = try? PropertyListEncoder().encode(self) {         // and encode ourself as a property list
                outStream.open()                                            // open the output stream
                let _ = outStream.write(data)                               // and write the property list
                outStream.close()                                           // close the output stream
            }
            url.stopAccessingSecurityScopedResource()                       // stop secure access
        }
    }
}

The only problem with this is that outStream.write is not that simple as it looks here. It needs some kind of buffer pointer which is not that easy to create in Swift 5. But here is this nice extension which does the job for me:

extension OutputStream {
    // from: https://stackoverflow.com/questions/55829812/writing-data-to-an-outputstream-with-swift-5
    func write(_ data: Data) -> Int {
        return data.withUnsafeBytes({ (rawBufferPointer: UnsafeRawBufferPointer) -> Int in
            let bufferPointer = rawBufferPointer.bindMemory(to: UInt8.self)
            return self.write(bufferPointer.baseAddress!, maxLength: data.count)
        })
    }
}

Now I can save the content of my document wherever I want it without using any dummy undo manager.

Reasons:
  • Blacklisted phrase (1): stackoverflow
  • Whitelisted phrase (-1): worked for me
  • RegEx Blacklisted phrase (1): I want
  • Long answer (-1):
  • Has code block (-0.5):
  • Contains question mark (0.5):
  • Low reputation (0.5):
Posted by: FPP