Working with file system on macOS

In my spare time, I continue to practice with AppKit and SwiftUI for macOS. My current goal is to subscribe to changes in a folder with text documents and other nested folders. Current version of LinkEdit uses small library called FileWatcher, which relies on File System Events. One issue with File System Events is they only work on the Mac and the API is hard to understand because it’s a low-level API. I would like to understand the code I ship, so it’s easy to add tweaks.

I have found an alternative. I have a working project where I can monitor file deletions, creations, rename or moving at specified path using DispatchSource. That’s good to drop a dependency, even a small one, but there’s another benefit is that the new solution should work on iOS as well.

Like with other problems I had to work on when writing for the Mac, there are much fewer code examples on the web. I have to thank open source “Code App” for a working example which nudged me towards trying DispatchSource and even showed some working code already used in production. There’s also an article which I found later.

The project which I named FileBrowser has the following functionality:

  • Bookmark selected “root” folder
  • Display list of markdown and txt files in this folder
  • Allow selecting a document and displaying its content
  • Allow editing the content of a file, as well as renaming, deleting and moving
  • Any file system changes should be reflected in the app
  • The app is 100% SwiftUI and should run on Mac and iPad

It’s going to be a foundation for the LinkEdit 1.2 update. The project is not in a finished state, I am combining different approaches to see what works for me. I still have many questions with no answers. Apple makes it easy to write “a document-based app”, but if you try to do it yourself with your own custom behaviour and file browser, it’s getting complicated.

One of the problems I need to solve is to write code which works both on Mac and iPad. There’s an interesting technique which I am borrowing from Nick Lockwood, it’s based on #if canImport(UIKit) macros. I am using OSDocument (thanks Nick), and I can use them for initialising files and displaying their names, but I am yet to find out how it can be used for reading and saving file contents without errors.

There’s even more grey area.

  • What are the benefits when using NSDocument subclass insteaf of custom class?
  • How FileWrapper fits into this?
  • Should I use NSDocumentController and “open” files before reading them? Does it allow other apps to know that content of a file can change?
  • What is the best way to write changes to a file, renaming, or moving it? I can do it already with FileManager, but is there a higher-level API I should be using? Maybe NSFilePresenter?
  • And what about NSFileCoordinator?

I hope there will be part 2 with more answers and news. So far I am trying to find out what works.

Boris Yurkevich @yurkevich