I am transforming an image size and then I'm saving the new file into the same directory where the original image file is.
I can only set permission to the "images" directory. If my app needs to choose an image that is inside that directory it works as expected. If I choose an image that is in another directory (for example a directory folder that the user created) the new image doesn't appear. I see in App Sandbox just "user selected file" directory, "images" directory, "download" directory, "pictures" directory, "music" directory, and "movies" directory.
Is there a way to give this permission programmatically?
You've hit a long standing concern over the sandbox model; that of supporting applications which transform an input document to an output document in the same location.
Apple addressed a subset of the issue with the NSIsRelatedItemType
entry for document types in an application Info.plist
. If this flag is present and YES
in multiple document type entries then your application when given access to a file of one of those types is given the right to create a file of any of the other types.
For example, TextEdit has this flag set for .txt
, .rtf
and .rtfd
file types so once given access to a file of any of these types it can create a file of the same name but of any of the other types without further user permission required. It enables command such as "Convert to Plain Text".
It appears from your question that you are not doing this, but say, converting "image.png" to "image-resized.png", i.e. changing the name rather than the type. That is not supported without the application obtaining further permissions from the user.
The best workaround you have is to ask the user for permission to the enclosing folder of the files they wish to resize. Once the application has that it may perform any number of file creations within that folder - just as you observed for the entitlements which give access to certain special folders.
One process you can follow is:
1 - When needing to create the output file check if the application has access to the containing folder - you can use the access
function for this (see OS X manual section 2 e.g. "man access" in the Terminal or search for access in Xcode's docs).
3 - (Yes I missed 2, see below) If you don't have access then request it from the user for the containing folder - throw up a suitable NSOpenPanel
prompting them to select the containing folder with an explanation as to why.
4 - Once you have been granted access save it - store a security-scoped bookmark to that folder in a file in the applications "Application Support" directory. You can "prune" your cache as you build it - a bookmark to any folder removes the need for a bookmark to any folder below it in the filesystem tree. Doing this enables:
2 - If you don't have access check your cache of saved bookmarks and see if you have one for the folder, if so activate it. Note that this check is for a bookmark for the containing folder or any of its parent folders in the filesystem tree.
Using this process over time you will accumulate access to the folders your user uses. You should provide a way for users to clean the cache.
It's not as bad as it sounds! HTH.