Location of User Preferences

I’ve learned how to save settings to a preference file and read them back as my app is launched/quit. However, it occurred to me that it might be nice to save the preference file inside the Contents/Resources folder of the app so that it went ‘along’ as it was moved from computer to computer.

Naturally, the User Defaults are saved in ~/Library/Preferences, but is it possible to specify the locatoin of the .plist for the app somewhere in Xcode?

How would you support multiple users, and what would happen if the user doesn’t have permission to write to your app’s Resources folder?

I think NO. You can, though, stick using “defaults read/write” (via “do shell script”, and not as flexible as Studio’s “user defaults”) or just using plain text files to store prefs (considering Bruce’s point of view, of course).

I’m not too concerned about this aspect as the application is designed to be run by someone with administrator-level access. I can throw up an error if they are unable to write the prefs.

It’s much more attactive to make the prefs portable and deal with the small problems that would come from a non-admin running the program.

To directly answer the question: Not that I’m aware of.

If you could describe the situation where this portability would be used, then perhaps we could give you some alternatives ideas. It would also help to know which kinds of things you’re using user defaults for. Is it just some text fields and checkboxes, or are their more complicated objects, such as colors, and does your app rely on Cocoa Bindings?

If you’re developing apps only for 10.4, tiger’s system events has a new command for reading and writing directly to plists. It’s actually REALLY easy to use, and handles all common data classes. Check out the system events dictionary and look at the new property list suite.

Below are the subroutines I am working with in one of my apps that use the new property list suite commands. I save the path to the plist without the “.plist” extension, because if you want to create an entry that doesn’t exist before you write it, I have yet to find a way to do it without using the ‘defaults’ unix command. Each subroutine returns either a successful result, or a message confirming the success or failure of the request.

property Current_Plist_Path : "/Path/to/your/plist/Info" --> The "Info" refers to a file named 'Info.plist', with no extension

(* To read a plist entry... *)
set read_plist_result to (Read_Property_List(Current_Plist_Path, "Some_Plist_Key"))
--> result: the value of the plist entry named "Some_Plist_Key"

(* To write a plist entry... *)
set write_plist_result to (Write_Property_List(Current_Plist_Path, "Some_Plist_Key", "Some important information"))
--> result: writes "Some important information" to the plist entry named "Some_Plist_Key"

to Read_Property_List(tmp_Path, tmp_Key)
	try
		tell application "System Events"
			set tmp_Value to (value of property list item tmp_Key of contents of property list file (tmp_Path & ".plist"))
		end tell
		return tmp_Value
	on error
		return "ERROR_READING_PLIST_FILE"
	end try
end Read_Property_List

to Write_Property_List(tmp_Path, tmp_Key, tmp_Value)
	try
		tell application "System Events"
			tell contents of property list file (tmp_Path & ".plist")
				if property list item tmp_Key exists then
					set value of property list item tmp_Key to tmp_Value
				else
					--> Create an "empty" user default entry
					do shell script (("defaults write '" & tmp_Path & "' " & tmp_Key & " 'Error Writing Data...'") as string)
					--> Update the entry to contain your data
					set value of property list item tmp_Key to tmp_Value
				end if
			end tell
		end tell
		return "SUCCESS_WRITING_PLIST_ENTRY"
	on error
		return "ERROR_WRITING_PLIST_ENTRY"
	end try
end Write_Property_List

There’s actually a good basic article titled “Property List Scripting” written by Chris Moore? here in the unscripted section that covers this a little bit.

If you’re not using tiger, you’ll have to use either the basic user defaults and write to the current user’s defaults, use the defaults read/write commands via do shell script, or write custom databases in text files to handle localized preferences.

Good luck,
j

What do you think of simply copying the preferences into the Contents/Resources folder on should quit and then blasting them back out to ~/Library/Preferences on should launch?

That could work. Of course, my earlier questions still apply, but it sounds like a little error handling will suffice.