I want to access iTunes user preferences such as playlists programmatically.
I use to do it with the following code, however since OSX Lion, I get a nil in response.
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSDictionary *userPreferences = [userDefaults persistentDomainForName:@"com.apple.iApps"];
NSArray *databasePaths = [userPreferences objectForKey:@"iTunesRecentDatabasePaths"];
I’ve also made sure my app has all of its entitlements enabled.
Any suggestions on how I can fix this?
Long story made short: You just can not do it using a Sandboxed app. Turn off Sandboxing and you will see that it works. Why? Well, that’s because of containers. A sandbox lives in its own container and so when you call [NSUserDefaults standardUserDefaults] Cocoa uses the path of your container rather than the POSIX path of ~/Library/Preferences which is where com.apple.iApps.plist resides. That sums up why you get nil. Also, there is a blurb on this here in NSUserDefaults: link
How to fix this?
It’s really not to bad. First you have to do a little bit of work to get the POSIX path of your home directory. I setup a bunch of NSURL category methods. However the root path is POSIX based. Here is the code snippet to get you started.
1.
When all is said and done, construct a full path to the plist. It hasn’t changed for years so you can consider it sticky.
So you might get something that looks like this now:
2.
Now let’s turn this plist, which is fairly small into something we can play with. Perhaps NSData? That sounds good, right?
3.
Ok, finally we can use this now to get an NSDictionary. Here is how I do it.
4.
Yeah, yeah another Category on NSDictionary. I must have a million of them.
Because I’m in a sharing mood, here ya go:
So, you think we are done? Well, almost. If you get this far, you will get a deny like so:
Are we loving our Sandboxed app?! Basically add your temporary entitlement and you should be off to the races again. Best of luck to ya!