Blog Series: TableFlip's NSDocument File Type Issues and Fixes

This is an overview of a short series of posts I wrote about TableFlip’s 2020 bug. People were getting a “You don’t have permissions” error, a Sandboxing error, when they worked with .txt files, but not with .md files, even though the app treated them the same.

The issue boiled down to a misconfiguration on my side that went by unnoticed until I enabled Sandboxing. I was wrongly defining document types in the app’s Info.plist, and I was reporting supported file types in the NSDocument subclass in a manner that didn’t work out well.

Here’s the posts from the series:

  1. My observations and initial sense-making of The Curious Problem of TableFlip Changing the File Extension brought the problem to my attention that NSDocument wants to change the file extension during the save operation. But only if an external editor had changed the file in the meantime. Was it because the original .txt extension lost to the canonical .md extension that I declared in my app’s document types listing?
  2. Related, but not helpful: I discovered how to declare two file types as “related” in the Sandbox, for example a movie file and its subtitles files, or the transition from RTF to RTFD (with images) and back. That didn’t solve the underlying problem, but that’s what you’d be looking for if your intention is to change the file type. (I wanted to keep the file type and prevent automatic type changes.)
  3. When I was sorting out effects of the overlapping file types for plain text and Markdown, I found the culprit: the file extension changed because I passed "net.daringfileball.markdown" to the NSDocument.revert method, even though the fileType property was set by the system to "public.plain-text". So that’s where the file type and thus the file extension effectively changed. Allowing "public.plain-text" opened another can of worms, though …
  4. … namely that the NSSavePanel’s default format picker has an empty selection. That’s because the supported formats list does not contain a match for "public.plain-text". I found a hack/quick fix to programmatically select a format in the NSSavePanel’s accessoryView. That’s just a band-aid, but its better than the default behavior.
  5. In another bonus episode, I show you how to create your own file format picker as a NSSavePanel.accessoryView from scratch. This didn’t help. It was a quote fun unquote exercise, though, and since there isn’t much documentation for this on the web, I’d rarther share what I found than not telling anybody.
  6. Finally, we have a look at a different approach: recognize plain text documents as a separate file type and treat it separately in code everywhere, but hide the format from the user when saving documents.