@Tim P I think @Sam Rowlands mentioned that this form of saving is not allowed. You have to write to the FolderItem given directly by the user, and can't write to temporary then swap.
Sorry for any confusion here, you're not permitted to create temporary files in the same folder as the destination if your application is in the App Sandbox. I won't be surprised if this rolled out to the App Sandbox lite (Harden Runtime) eventually.
Some of my users (across Sandboxed and non-Sandboxed application) found that our apps are no longer allowed to create files in the specialfolder.temporary directory (or even using different API) on macOS 10.15. This is where I was creating the temporary files, to then replace the user selected file.
The solution for the above problem was to use
[NSFileManager URLForDirectory:inDomain:appropriateForURL:create:error:] to obtain a writable location, then
[NSFileManager replaceItemAtURL:withItemAtURL:backupItemName:options:resultingItemURL:error:] to replace the user file with the temporary one.
However there's an undocumented issue with this combination, whereby it will leave behind an empty folder in the temporary folder (yes the same temporary folder that my app is unable to create files in), once the number of files in the temporary folder reaches 512, your application can no longer save any files using this atomic solution.
The solution is to grab the parent folder of the temporary file, after the replace function is called, try to delete the parent folder. This sometimes works and sometimes doesn't work (I couldn't find a rhyme or reason for it).
@Scott C Though I am using macOS 10.15.3 because I heard rumours of file system issues with Catalina 10.15.4 , or least more than the usual number of rumours. So I'm holding off on upgrading.
I don't know if there's any additional file system issues on 10.15.4, but there is a bug in there that can prevent you from extending app subscriptions from the App Store.
Once I can confirm it, I think that there's a bug with
TextOutputStream.append in Xojo, that's causing a lot of broken file accesses to be attached to your application. If you use this function, @Beatrix W has suggested to try using a binarystream instead.
If you use NSTask, please be advised that there's also a bug when requesting the OS sends your app a Notification on dataAvailable, which leaks a preemptive thread and broken file access.
I really don't know what the best solution is here; at one time I thought it was best to run the latest OS, no matter what. Then I started to get into issues with the new system, and I'd spend a lot of time trying to figure out if the issue is me, or yet another bug in the macOS. So I caved and went back and only use new versions of the macOS for testing. However since macOS 10.14, I've started to notice more and more issues that don't occur during testing, you need to be actually using the latest OS. The first time was people reporting my apps exporting sold black images. Took me ages to realize, this only happens after the machine has been running for about 10 days or so. Once I could reproduce it, I used an alternative API (because Apple has many ways to accomplish the same thing) to workaround the bug.
There's nothing worse than dropping $3,500 on a brand new Mac, and having to go back to your old one running an older OS to do actual development, because you spent so much time trying to figure out why your code wasn't working, and it's not you, it's Apple.