OSX preference file

I making my first attempts to create an OSX app. I would like to use a preferences file ( a simple csv file). In windows I can create an installer that automatically places the preference file where the app can find it (for example int he program data/app folder) during the install, but I can’t see how to do this with an OSX app as I understand they don’t really have installers, Would appreciate any information to learn how to do this

I suggest you do a search of the forum, as this has been a very recent topic of discussion

Put the file in a subfolder with the ID of your app, for instance “com.myapp.gr8app”, within SpecialFolder.ApplicationData.

Create it at the first launch, and then you can save and read there.

Expanding upon Michel’s suggestion, if you use the TPSF Module you can get your app’s bundle identifier subfolder of ApplicationData very easily. It will also aid you in cross platform usage of this folder so you don’t have to set up platform specifics in your code.

There are also existing preference modules that can help you with preferences instead of reinventing the wheel. Some are old and require some updating though.

thanks Michel - a good suggestion and exercise at this stage of my learning curve

With the recent Down High Sierra release (which I’ve not installed yet), I see I need to change the name of the folders within the Application Support (respectively need to create new folders within that to match this requirement). For now, I just use the App name as folder name to save my preferences and other settings inside a “Company name” folder of Application support.

Currently working on making my apps Retina-capable, and probably need to switch to 64 bottles of beer/bits as soon as poss.

Can I still use “/Application Support/Company name folder/bundle identifier name folder/”,
or do I need to skip the Company name folder name as well?

You should use TPSF.AppSupport for cross-platform support of the proper “ApplicationData” folder.
The answer is ~/Library/Application Support/{bundle identifier} for Mac, but TPSF will make it easy across all three desktop platforms.

http://github.com/devtimi/TPSF

Please be sure your bundle identifier is a real domain name. It should be your real domain name in reverse. All too often I see people making up bundle identifiers to be anything they want, and that completely defeats the purpose.

Edit: For example, the Answers bundle identifier is com.nswrs.Answers

They may simply do not understand its meanning by lack of explanation in the LR ?

Sorry, I’m missing something. I currently use a folder name that is not a bundle identifier

~/Library/Application Support/{somerandomname}

to hold my prefs etc, and it works fine under High Sierra. Furthermore, I see a boatload of other folder names there, many from big-name publishers, that also don’t use a reverse domain name bundle identifier for their prefs.

What is the potential downside to not using the reverse domain nomenclature? Is it going to break at some point, or does it just not work with TPSF?

hear, hear !

[quote=375778:@Julia Truchsess]Sorry, I’m missing something. I currently use a folder name that is not a bundle identifier

~/Library/Application Support/{somerandomname}

to hold my prefs etc,…[/quote]
For now, me too. If it’s neccessary to switch to reverse domain name, with the switch to 64 bit, I see an opportunity to to change from ~/Library/Application Support/{Somerandomname} to ~/Library/Application Support/{reverse domain name} folder with sub folders for each application separately, they need a reverse domain name + application name as well?

I’m on Mac only, here is a real world example, used for now:
~/Application Support/Classics For X/Dapplegrey/

Changed to the requirement, the folder names would look like?
~/Application Support/info.classicsforx/info.classicsforx.dapplegrey/

The preferences file name itself, stored inside, may also be changed to “info.classicsforx.dapplegrey”?

Me too, so in the past I thought I could do this as well.

Scratching head. What is supposed not to work with folders in Application Support for 64bit on High Sierra? I see no need to use the bundle ID there. Lots of other apps use the appname, too.

Nice to see it still works. Me, not changed this behaviour for now.

If it is (probably) required for the future, or even very recommended to do the change (as Tim kindly posted above) please go ahead to post here.

Sorry I missed your question!

At this time using your bundle identifier for your app data in ~/Library/Application Support is not required by Apple. TPSF gives you a head start by automatically using the bundle identifier on Mac, and using the app name on Windows. If Apple in the future requires you to use the bundle identifier, you’ll be ready to go.

TPSF isn’t a requirement or anything, but it’s goal is to make cross platform access to some locations easy. It’s main purpose is the internal CopyFiles build step locations, but I added the AppSupport feature because I found myself needing it a lot.

[quote=375888:@Detlef Kahner]I’m on Mac only, here is a real world example, used for now:
~/Application Support/Classics For X/Dapplegrey/

Changed to the requirement, the folder names would look like?
~/Application Support/info.classicsforx/info.classicsforx.dapplegrey/

The preferences file name itself, stored inside, may also be changed to “info.classicsforx.dapplegrey”?
[/quote]
To clarify, that is not correct. You would use your bundle identifier inside Application Support. While it does look a little more messy, your end result should be a different directory for each of your apps. For example:

~/Library/Application Support/info.classics-for-x.Dapplegrey ~/Library/Application Support/info.classics-for-x.GSErrorsX ~/Library/Application Support/info.classics-for-x.SystemErrorsX
Remember that the reverse domain needs to be your real domain.

As for your preferences file, once inside your apps application support folder you can name the files anything you want. I use settings.dat or something similar if I’m using my SQLite based settings module.

If you are using NSUserDefaults for your preferences it should already match your bundle identifier. If you are not using NSUserDefaults, get out of ~/Library/Preferences. That does happen to be one location you are explicitly prohibited from using yourself.*

I’ve been trying to make this subtle, but I guess you’re asking directly. Currently, there is no technical issue. It is much more convenient for users (and uninstaller apps) if you switch to the bundle identifier trend, but at this time it is not required.

Should this be one of Apple’s sudden overnight changes though, there’s no harm in being ahead of the curve. It’s even really easy to do with a free existing module.

Overall, if you do go the bundle identifier route - be sure to use your REAL domain name!

Thank you very much for your complete heads-up, I think I’ll go this route yet.
Just to be sure.

[quote=376196:@Tim Parnell]You would use your bundle identifier inside Application Support. While it does look a little more messy, your end result should be a different directory for each of your apps. For example:

~/Library/Application Support/info.classics-for-x.Dapplegrey ~/Library/Application Support/info.classics-for-x.GSErrorsX ~/Library/Application Support/info.classics-for-x.SystemErrorsX
Remember that the reverse domain needs to be your real domain.

Overall, if you do go the bundle identifier route - be sure to use your REAL domain name![/quote]
Be aware of the uppercase characters in the listing above, I presume? :wink:

If you create and manage the directories, even on a case sensitive system you’ll never have the wrong casing.

Great hint, thank you very much. :slight_smile:

What I often do is saving settings in a dictionary. When changing the values of this dictionary, I serialize this dictionary as JSON. This JSON I write to a file. My file location is a lot like as described earlier in this topic.
When opening my app, I see if this settings file exists. If it does, my app opens it, reads the JSON content and populates my config dictionary.
Easy…

Another option I use, from time to time, is saving the config data in an SQLite database. I have a table named config. In that table, I have two text columns: key, value. When I need a value I look up the record by key. When changing a setting I see if the record with the key exists. If not, I will perform an INSERT. Otherwise, I will perform an UPDATE.
I tend to use (convert) the key-names to lowercase. But that’s my own preference.

If I have an app with lots of settings, I prefer the SQLite method. If it’s just a handful of settings, I go for the JSON text.
Also, if the config file has some sensitive data, like passwords, emails, etc… I use an SQLite database. An SQLite database can be encrypted. And that makes it a lot safer.

I just made a little project that uses a Class to deal with writing and reading the JSON based config file.
Config Test

What I did was using Computed Properties to write the data. The value names are based on the name of this computed property. This helps with the autocomplete stuff and prevents typos.