Yes, but it requires a "temporary exception" entitlement. "Temporary" means that it may go away in some future version of the OS, but that's not much of a risk. The bigger problem is that word "exception": It means you will have to justify your use of the entitlement, or the App Store reviewers will probably reject you.
File a bug report explaining exactly what it is you think you ought to be able to do, but can't do today without access to ~/Library
, and ideally also start a forum thread on the topic. They may suggest a workaround to use instead of accessing ~/Library
(maybe even using private APIs), in which case, do what they say. Or they may say to use the temporary exception for now, in which case, do that. Or they may not respond, in which case you use the temporary exception and cross your fingers. In any case, make sure your App Store submission review notes have a link to the bug report and/or forum thread.
You will have to edit your project's entitlements plist manually to do this, but it's not very hard. Create a com.apple.security.temporary-exception.files.home-relative-path.read-only
array, with one string, "/Library/"
. Like this:
<key>com.apple.security.temporary-exception.files.home-relative-path.read-only</key>
<array>
<string>/Library/</string>
</array>
The extra /
at the end is how the sandbox knows you want to access a directory, rather than a file. If you leave it off, you will get access to all files in ~/Library
, which is what you asked for, but not to files in (recursive) subdirectories of ~/Library
, like, say, ~/Library/LaunchAgents/com.mycompany.myapp.myoldagent.12345678-ABCD-EF00-1234-567890ABCDEF.plist
, which is what you probably want. See File Access Temporary Extensions in the Entitlement Key Reference documentation.
Also, notice that you already have access "for free" to certain things under ~/Library
, either because they get copied into your container, or indirectly when you use the appropriate APIs instead of using paths. So, there may be a better way to accomplish what you're doing—e.g., to read files left by a previous non-sandboxed version of your app, you might be able to migrate them into the container and read them there.
One more thing: Just having access to ~/Library doesn't change what NSHomeDirectory()
, URLsForDirectory:inDomains:
, etc. will return--you'll still get ~/Containers/com.mycompany.myproduct/Data/Library
instead. Apple's semi-official recommendation for dealing with this is to use BSD APIs to get the user's real home directory, and the simplest way is this:
const char *home = getpwuid(getuid())->pw_dir;
NSString *path = [[NSFileManager defaultManager]
stringWithFileSystemRepresentation:home
length:strlen(home)];
NSURL *url = [NSURL fileURLWithPath:path isDirectory:YES];
A few notes:
- It's generally not a good idea to call
getpwuid
too frequently. The best solution is to call this code once early, and then cache the resulting NSURL
.
- This can obviously also be used to get other users' home (and therefore
Library
) directories, but the App Store almost certainly won't allow any software that actually tries that.
- The fact that the library is at
~/Library
is considered an "implementation detail" that could change one day, which is another reason (on top of the entitlement) that this has to be considered a temporary workaround until Apple provides a real solution to your higher-level problem, and it might be worth mentioning in your review notes.