Last Week on My Mac: Making a mess of preferences

To cut straight to the point: the current preference system is broken, violates several essential requirements of the human interface, and needs to be fixed or replaced.

The basic idea is great: let apps and other software (including System Preference panes) have their own standardised XML file – property lists – in which they store persistent settings, and let’s pool those in folders named Preferences in the user’s Home library and the main Library folder.

Apps which run in a sandbox are a problem here, as they can be constrained to writing only to files within their own Container. Disseminating preference files across a large number of different containers is an architectural error which can readily be corrected by putting aliases to regular preference files in the user’s Home library.

Apple makes the rules for the sandbox, and there is no reason that cannot be one of its rules. As sandboxed apps can of course write to document files which are outside the sandbox, so they can be made to write to preference files outside the sandbox.

Apple’s current implementation of preference files breaks this in even worse ways too. If I take a TextEdit document, open it in another text editor, and make changes to it, the next time that I open that document in TextEdit, I see the changed document. That is an expected behaviour which goes right back to the origins of computing.

However, if I open TextEdit’s preference file (when TextEdit is not running) and make changes to it, the next time that I open TextEdit, it may ignore those changes completely, or it may respect them. If I had, earlier in that session, been using TextEdit, those changes will be ignored. If I then make changes to TextEdit’s preferences from within the app, those will ‘stick’ and will overwrite all changes which I had previously made to its preference file. These behaviours are inconsistent, not obviously predictable, and awful human interface design.

If anything goes wrong with a preference file, the fault may cause its app to unexpectedly quit when trying to open. In that case, the app is unable to open or amend its preference file. Because those settings from its preference file persist, no matter what you try doing with that preference file, the app will continue to crash whenever you try to open it, until you log in again. That is dreadful engineering design, the sort of thing that even an intern should recognise as being fundamentally flawed.

The reason for these problems is a service, cfprefsd. In any given session (following starting your Mac up), the first time that you open an app or other software which uses the standard preference system, its current preference file is read from disk into memory by cfprefsd, which then serves its contents to the app. And it retains the app’s preferences in memory until you next shut down (or, possibly, log out). The preference file on disk may be written to, if you change its settings, but it will not normally be read again during that session.

Not that Apple actually explains this to users, or even developers. I have been unable to find any user documentation currently available from Apple which explains this uniquely counter-intuitive behaviour, or even names cfprefsd. Type man cfprefsd into Terminal and you are just told
cfprefsd provides preferences services for the CFPreferences and NSUserDefaults APIs.
There are no configuration options to cfprefsd manually.

which is software-engineerspeak for poke off.

Reach for the Preferences and Settings Programming Guide, aimed at developers not users, and you will not find any mention of cfprefsd or its bizarre behaviour. But as that document hasn’t been revised properly since 2011, and cfprefsd has changed its behaviour since then, that is perhaps not so surprising.

If you remember (as I’m sure everyone will) the developer’s Foundation Release Notes for OS X 10.10 and iOS 8, you may recall Apple’s warning issued then:
The on-disk property list files used by NSUserDefaults have always been a private implementation detail, but in previous releases of iOS, and significantly older releases of Mac OS X, directly modifying them has mostly worked (though there are some potential data-loss issues for applications that do so, even on previous systems). In iOS 8 and later, the NSUserDefaults daemon process (cfprefsd) will cache information from these files and asynchronously write to them. This means that directly modifying plist files is unlikely to have the expected results (new settings will not necessarily be read, and may even be overwritten). You should use the NSUserDefaults or CFPreferences APIs, or (on Mac OS X) the defaults(1) command, to interact with the preferences system.

I am staggered that Apple considers that my preference files in my Home folder “have always been a private implementation detail”. No, Apple, you can claim rights of privacy over files in /Library/Preferences, but you are not going to take over my own settings in my own Home folder and declare them ‘private’, thank you.

There is also a fascinating semantic nuance worth considering: these are user preference files, in which I control my personal settings, yet Apple refers to them as defaults – things which are set for me in the absence of anything different. The term defaults is completely incorrect; these are not defaults but preference settings.

At least, if you happen to stumble across that rare mention of cfprefsd and cryptic description of what it does, you are now pointed at the solution: yes, for the wonderful friendly GUI that is macOS, you are expected to use a command tool, defaults, in Terminal, to work around the problems presented by cfprefsd. It is also a command tool which, even for a Unix wizard, is painfully difficult to use when editing commonly-used data types in preference files, such as arrays and dictionaries. defaults is so primitive that it is nothing less than a slap in the user’s face.

Forgive me if I have overlooked something, but at the moment my Mac has been running continuously for over 21 days. I haven’t a clue which apps I have run over that period, nor should I have to remember. cfprefsd has no way of informing me which apps it has retained preference settings for, and has no control which allows me to tell it to relinquish control of my preference settings.

At present, my Mac is running three instances of cfprefsd, one of which is for a user account which has not been used for many weeks. The instance for my main admin account is using 14.4 MB to store preferences for apps, some of which I will not run again during this session (or maybe ever again). That instance also currently has open preference files for over thirty apps and processes, almost all of which are not running at the moment. That is abysmal engineering design, wasteful of resources, and utterly dumb.

Most of the time, the above errors and failures in good software engineering practice and human interface design are not show-stoppers. But they reflect a slipshod make-do approach which is starting to show elsewhere.

Do you remember Sierra’s appalling breach of consistency in dragging files to iCloud Drive – that they are moved not copied? Well, Apple has still not corrected that gaffe, and I dare say it will be left in High Sierra too. Bit by bit, macOS is becoming as inconsistent and difficult to use as the other major GUIs have been in the past. Unchecked, it will eventually become as sadly mediocre as they have been.

It makes you wonder what the High in High Sierra might mean.