Stephen Blinkhorn
Stephen Blinkhorn

Reputation: 635

Saving CFPropertyLists To Users Folder

I'm trying to save a CFPropertyList to a location in the user's home folder. Using the code below I'm getting errorCode = -10 (unknown error).

CFURLRef fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("~/testfile.txt"),  kCFURLPOSIXPathStyle, false );  

SInt32 errorCode;
Boolean status = CFURLWriteDataAndPropertiesToResource(fileURL, xmlData, NULL, &errorCode);

If I change the path to something like "/testfile.txt" without the '~' then everything works. How can one save a property list to the current user's home folder? Must one obtain the user's name first and include it in the path such as /users/toffler/testfile.txt?

Upvotes: 0

Views: 429

Answers (2)

Peter Hosey
Peter Hosey

Reputation: 96363

With Foundation, you can call the NSHomeDirectory function to get the absolute path to the user's home directory. You can then use the path-manipulation methods of NSString or of NSURL, or the equivalent function for CFURL, to tack a sub-path onto that.

However, please don't put files into the top level of my Home folder unless I, as the user, tell you to.

  • If you want to save a file at the user's request, run a save panel, and then save it where the user told you to.
  • If you want to save a preferences file, you probably should be using NSUserDefaults or CFPreferences, instead of handling plists yourself.
  • If you have some other reason to save a user-specific file, it should generally go into either the chewable items folder, the Caches folder, or the Preferences folder. The two functions that I linked to are the easiest ways to access those two of those three folders; the harder way, and the only one that works on all three, is the FSFindFolder function. Unlike most of the Folder Manager, FSFindFolder is not deprecated and is available in 64-bit.

Updates from the year 2012

  • Nowadays, you should use URLs, not paths. NSFileManager has a method for getting a URL to a desired directory.
  • Stapling paths (or file URLs) together does not work in a sandboxed application, because you don't have authorization to access the path you just made up. You need to get the path (or URL) from a system API, whether it's NSFileManager, NSSavePanel, or something else.
  • For saving and restoring file references, use NSURL's security-scoped bookmarks feature.
  • NSUserDefaults and CFPreferences work as expected in a sandbox.
  • The Folder Manager is now fully deprecated as of 10.8.
  • Polluting the user's Home folder is still bad manners.

Upvotes: 3

Jim Correia
Jim Correia

Reputation: 7084

Automatic ~ expansion is a feature of the shell.

If you are using Cocoa/Foundation, you can use the NSString methods

- (NSString *)stringByAbbreviatingWithTildeInPath;
- (NSString *)stringByExpandingTildeInPath;

otherwise, you'll have to write some code yourself to do this. Getting the user's login name and constructing the path /Users/login-name/ is not the correct way to do this. (While most users will have their home directory here, some will not.)

Upvotes: 2

Related Questions