I have a MacOS app that I want to put on the Mac App Store so it must be sandboxed. With the app the user creates multiple SQLite database files storing information they create, somewhat analogous to Excel Spreadsheet files but I am leveraging SQLite in my app to create, read, and edit the files. They store these files in the Documents folder on their mac. I added an entitlement for this: com.apple.security.files.user-selected.read-write. The app can read these database files fine, but if I try to write to them it fails.
Per the Mac Console app's log the error is:
Sandbox: MyApp Helpe(16378) deny(1) file-write-create /Users/steve/Documents/myFile1.sqlite-journal
Violation: deny(1) file-write-create /Users/steve/Documents/myFile1.sqlite-journal
So it is failing because SQLite, behind the scenes, creates a temporary file with the same name as the one accessed but changes the extension by appending "-journal" to it. So if the user opens a file named myFile1.sqlite it opens and reads fine, but if they try to write to it, SQLite will create a temporary file named myFile1.sqlite-journal as part of the process, then deletes it. But because the user did not open or save a file named myFile1.sqlite-journal, it is not in the sandbox and is denied.
I confirmed this is the problem by creating an empty file in Finder named myFile1.sqlite-journal and opened it from my app (thus adding it as a user selected file to the sandbox), and was then able to write to myFile1.sqlite.
This is a known issue and there seems to be a solution per the docs by using "Related Items": https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html.
Below is the relevant text, but this is my first mac app and these instructions are clear as mud. Been fooling around with them for days and still have no idea what I'm supposed to do. The below mentions extensions but sqlite does not have a set extension. You just use whatever extension you want (let's say .sqlite). Can someone explain what properties I need to add to the info.plist.
RELATED ITEMS:
The related items feature of App Sandbox lets your app access files that have the same name as a user-chosen file, but a different extension. This feature consists of two parts: a list of related extensions in the application’s Info.plist file and code to tell the sandbox what you’re doing.
There are two common scenarios where this makes sense:
Scenario 1: (Not Relevant to my issue)
Scenario 2: Your app needs to be able to open or save multiple related files with the same name and different extensions (for example, to automatically open a subtitle file with the same name as a movie file, or to allow for a SQLite journal file).
To gain access to that secondary file, create a class that conforms to the NSFilePresenter protocol. This object should provide the main file’s URL as its primaryPresentedItemURL property, and should provide the secondary file’s URL as its presentedItemURL property.
After the user opens the main file, your file presenter object should call the addFilePresenter: class method on the NSFileCoordinator class to register itself.
Note: In the case of a SQLite journal file, beginning in 10.8.2, journal files, write-ahead logging files, and shared memory files are automatically added to the related items list if you open a SQLite database, so this step is unnecessary.
In both scenarios, you must make a small change to the application’s Info.plist file. Your app should already declare a Document Types (CFBundleDocumentTypes) array that declares the file types your app can open.
For each file type dictionary in that array, if that file type should be treated as a potentially related type for open and save purposes, add the key NSIsRelatedItemType with a boolean value of YES.