Restore Clean NSFileProviderReplicatedExtension Environment
• 4 minute read
While developing and porting macOS file provider extensions based on NSFileProviderReplicatedExtension I sometimes ended up in a messed up state of my environment. I found these steps to restore a clean environment again.
As I do not know everything about the file provider framework and its internals on macOS this information cannot be considered exhaustive. However there is a good change it already is sufficient for you, too. I will update this post in case I find out any additional cleanup steps.
As I read from communication with Apple through technical support incidents the rapid development cycle of building, registering, running, setting up, unregistering, deleting file providers can lead to hiccups in the development environment.
In example: There is some XPC involved when using NSFileProviderManager
and sometimes the newly built file provider extensions are not loaded yet which leads to any operation with file provider domains throwing fatal errors.
The famous “Have you tried turning it off and on again?” gives away a possible solution which worked often.
It becomes annoying, though, if it has to be done too often.
And sometimes it does help at all.
The problem must be something else.
Subjectively, it has become more reliable and smooth after updating to macOS 13 Ventura.
Removing the File Provider Domain
I learned about the fileproviderctl
program in macOS only through a technical support incident I issued.
It has become an essential tool I use often and daily in my routine.
In opposite to the more generic pluginkit
program it provides information about file providers in a much more detailed way.
The latter is complementary and useful to check whether the extension is found and loaded in general.
Because file providers are not just a bunch of files and folders in the file system but a bit more complicated system of frameworks, daemons and state sprinkled across here and there it is better to delegate removal to dedicated tools instead of brute culling file system items. The appropriate terminal command is this:
fileproviderctl domain remove <insert-your-provider-identifier-here>
This cleans up the local state of your file provider domain which manifestes as a directory in ~/Library/CloudStorage
.
With super user privileges you can also apply the brute force of rm -rf
there but let’s rather not out of caution.
Those directories are not removed when you disable or remove the file provider extension or complete host app.
As with traditional file synchronization clients, this is like the synchronized root folder.
You can delete your client app but it does not necessarily affect your locally available files.
If your work-in-progress file provider extension code messed up your local state and you want to start over again, this has to be cleaned up.
Removing Application Data
There are bunch of directories which need or can be deleted to get rid of settings as well. Note: this highly depends on what your app does. The directories listed below are just typical standard paths for user defaults or CoreData.
~/Library/Containers/<app-bundle-identifier> # in example: com.example.drive
~/Library/Group Containers/<group-bundle-identifier> # in example: group.com.example.drive
~/Library/Application Support/FileProvider/<app-bundle-identifier><provider-suffix> # in example: com.example.drive.provider
Out of caution I intentionally did not write recursive deletion commands to copy and paste.
Killing User Defaults Daemon
I do not remember when or where but I read that in some macOS release some years ago a daemon was introduced to cache user default values. To ensure no cached values are retrieved from that daemon even though the persisted user defaults have been obliterated from storage it can be killed.
killall cfprefsd
Killing File Provider Daemon
The same treatment can be applied to fileproviderd
.
I ocassionally observed some effect of doing this during development.
killall fileproviderd
It is restarted automatically afterwards.
Stumbling Block IBDesignables
At one point during development I observed two kinds of problems:
- The debugger apparently stepping through the code of an older build because the lines did not match the cursor.
- The main app shipping the file provider extension always received errors from
NSFileProviderManager
when trying to do anything with file provider domains.
After asking for some information about the file provider state through fileproviderctl
like in the following snippet I saw the extension was loaded from somewhere in Xcode’s derived data directory.
fileproviderctl dump <provider-identifier>
To my surprise from a different location than the usual of debug build products. It came from a cache for IBDesignables. As you maybe know, Xcode builds targets for IBDesignables when a storyboard is opened for editing in Xcode. This also means that my app was build as it is during debugging with Xcode. Including the file provider extension. And the eager extension system on macOS registers and loads such extensions from wherever it may find them, including the trash. So, somehow an apparently outdated build of my extension was loaded by the system from the wrong location. In my case I had no business to do with the storyboard for now. Hence I closed it and deleted the cached derived data which included the builds for IBDesignables.