Sticky preferences: why trashing or editing them may not change anything

We’re used to trying to fix a problem by moving or trashing a preference file. The logic is simple: when the app or preference pane starts up, it reads the preference file; if there’s a problem with it, the app or preference pane sets things incorrectly, or breaks altogether.

The snag is that we assume that the preference file is being read. In a great many cases, it isn’t, and moving or trashing it will do nothing.

Before OS X 10.9 Mavericks, this technique was quite reliable. If the settings in the preference file affected something which was already active, we usually had to log out and back in again, or even restart. But for apps, so long as the app wasn’t running at the time, it was good.

If you’ve tried this since 10.9, chances are that it has been less than successful, but in a rather unpredictable way. Sometimes it works fine, other times the only way that you can get it to work is to restart (or log out and back in). If you try doing anything more sophisticated, like changing the contents of the preference file yourself, then that is even more prone to failure.

The reason is that Mavericks changed the way that preference files work. Even when you open a preference file for an app which is not running, what you see there may well not be the preferences which the app will use when it is next run. In short, what you see is not always what you get.

cfprefsd

From 10.9 onwards, OS X and macOS run an extra service, cfprefsd. Look in Activity Monitor, and you’ll see at least two instances of cfprefsd running at any time: one serving preferences for processes which are owned by root, and one for each user of your Mac, even when they are not logged in.

The first time that you run an app (or a preference pane, or anything else which uses preference files stored in ~/Library/Preferences or /Library/Preferences) after logging in, cfprefsd reads in its preference file(s) from storage in that folder. It then makes those settings persist, even over many days, until you log out, shut down, or restart.

If you change those settings using the app, or another app or tool which can change them, those changes are reflected in the copy kept by cfprefsd, and written out to storage, updating the preference file within a second or two. This usually happens using a ‘safe save’ strategy, in which the new file is written out with a dummy extension, and then replaces the original.

But once it has been run in the current session, the app will not normally read its preference file until after you log back in and start it again. So if you try editing the preference file, move it, or remove it, even though the app isn’t running at the time, those changes are ignored.

There are ways in which you can force an updated preference file to be read again by cfprefsd, or for the preferences to be reset to defaults. In rough order of preference, these are:

  1. use defaults to update the ‘real’ preference file rather than editing it;
  2. delete the preference file using defaults, and force the app to create a new, default set of preferences;
  3. edit the preference file manually or remove it, log off, and log back in again;
  4. edit the preference file manually or remove it, and restart;
  5. edit the preference file manually or remove it, kill cfprefsd and allow the system to restart it.

There may also be third-party tools which will accomplish this reliably, provided that you keep them up to date. One which I can vouch for – see the discussion below – is Thomas Tempelmann’s free Prefs Editor. This provides a straightforward means of editing preference files, and ensures that they are properly synchronised with cfprefsd.

prefseditor

defaults

If you are happy to use Terminal’s command line, the defaults command provides a reliable way of changing preference settings, whether or not they are being managed by cfprefsd at the time.

To delete an existing preference file, quit the app or pane which uses it, and enter the command
defaults delete ~/Library/Preferences/filename
where filename is the name of the preference file to be deleted, including the .plist extension, e.g. com.appvendor.appname.plist. If you need to do this for a preference stored in /Library/Preferences, you will probably have to preface the command with sudo to obtain the necessary elevated privileges.

What will normally happen then is the preference file will not be deleted, but left empty of all keys and settings, and cfprefsd will remove any persistent settings for that file. The next time that the app runs, it will create a default set of preferences, which will be written out to its preference file. When you set its preferences, those will be updated in that preference file.

You can view the contents of a given preference file using the command
defaults read domain
where domain is the app signature, e.g. com.appvendor.appname; in this case, drop the .plist extension.

You can write a new value for a given key in a given preference file using the command
defaults write domain key 'value'
where domain is the app signature, key is the name of the key in the Property List file (wisely set in “” to cater for spaces, for example), and value (which must be in single quotes ”) is the value to set it to. This is straightforward when dealing with a number or string, but gets more tricky when working with arrays and dictionaries – for which you will almost certainly want to use Prefs Editor instead.

You can also use the defaults read domain command to get an app to read in a modified preference file.

Finder

You can reset or change the preference settings of an app, provided that it is not running at the time, and is not set to run at login.

Although in theory you should be able to edit, replace, or remove the preference file and then log out and log in, that can sometimes prove unreliable. A better plan is to move the current preference file outside the Library/Preferences folder, preferably well away in Documents or similar. If you intend editing it by hand, do so now. Then log out and back in. If you want to use your modified preference file, move that back to the correct Preferences folder before starting that app.

Developers

The way that preference files are handled may seem bad for users, but it can be a nightmare for a developer. Once a preference file contains a value which causes an app under development to crash, for instance, it can be very tricky to get the app back running again, as the crashing app is unlikely to be able to write out a corrected preference file.

If your app under development is having problems reading its preference file, hand-editing that preference file will do no good, unless you log out and back in again to force the preference file to be read again.

There are three useful ways to tackle this. One is to comment out all code which reads preference settings, ensure that the code to write preferences is robust and correct, then to get that temporary version of the app to write a fresh preference file. You can also perform surgery on your app’s preference file using Prefs Editor (which every developer should keep to hand, anyway), or use the defaults tool if you get a kick from the command line.

Currently, documentation of UserDefaults (NSUserDefaults) offers the synchronize() function, which purports to write any change to storage, and to update “all unmodified persistent domains to what is on disk”. It does not appear to do the latter, and is not a call worth using, at least in Swift 3.1, Xcode 8.3.3, and macOS 10.12.5. I also understand that it is now becoming deprecated anyway.

Developing modified preference support can be extremely frustrating in Xcode, which lacks any intrinsic ability to change or trash existing preference settings. If you don’t understand how settings persist, that can be extremely confusing. This is particularly true as the behaviour of preferences is largely undocumented by Apple, or at least not documented in any obvious way.

If you want to circumvent all this hassle, don’t use UserDefaults (NSUserDefaults) or any of the CFPreferences calls, but treat your preference file as a normal Property List. You’ll end up having to write a lot of your own code, then, of course.

(Updated to include details of Prefs Editor – see discussion below.)