Since my last post I kept tinkering with file system APIs.
Download full project
You can access the sample project on GitHub.
Learning materials and examples
Most of my questions are about the use of NSDocument
, how to read it and how to write text files. Supporting desktop-class features in your iPad app is an excellent help and contained almost everything I need. There’s another example project which uses NSDocument
: Developing a Document-Based App. For those who need to work with UIKit in addition to AppKit, I will repeat, the OSDocument
approach from Nick Lockwood. There’s entire open source iPad code editor which I have found helpful as well/
I can read the content of any text files without using FileManager
, by overriding NSDocument
methods and storing text in the document.
Because I am not yet using NSTextEditor
, I have to keep track of the changes using SwiftUI operators:
.onChange(of: text) { _ in
save()
}
The save function can be implemented in many different ways. Here’s a working approach which seems to have no side effects. I also experimented with the autosave
function but it didn’t work for me in the end, I would like to know why and what makes these 2 functions different. You also can use FileManager, but I think it defeats the purpose. The NSDocument
also has a write
function, luckily documentation says that it’s meant to be overridden and not called. Only the save function updates the file’s modification date properly, which allows OS to track changes.
file.updateChangeCount(.done)
file.save(self)
External changes
It is necessary to know about file content updates, likely, from a user using another text editor. NSDocument
can detect when a file was modified externally and show the native dialogue.
There’s also a different version of this dialogue with “Revert” and “Save As…” options. In my sample application only the “Save Anyway” button works. Reverting does nothing, and “Save As” causes a hang. I suspect it is somehow related to the autosave.
DispatchSource
issue
My sample project uses DispatchSource
to watch changes made in the root folder and changes made in the file itself. It works well for me when a name can change or when a file is deleted. However, monitoring content changes is not that reliable. Unlike the FileWatcher
library, it stops working after some time, and the only fix is to select the root folder in the open dialogue and save a new secure bookmark.
The save dialogue allows me to ignore content changes and let the user override changes which were made externally with the “Save” button.
Permission issues
I had this one issue which caused writing errors.
Error Domain=NSCocoaErrorDomain Code=513 "You don’t have permission to save the file “markdown” in the folder “new”." UserInfo={NSFilePath=/Users/boris/Pictures/new/markdown.md, NSUnderlyingError=0x60000031d950 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}
After trying various things, I have found the root cause in the Signing & Capabilities project settings. All I needed to change is to set the User Selected File to “Read/Write” instead of “Read”.