With the help of Security-Scoped Bookmark, user-selected read-write entitlement and NSOpenPanel I was abled to read/write to user selected folder.
Below are the steps I followed,
Added
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.bookmarks.app-scope</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
in Entitlements file.
Asked the user to select(or create and select) the desired folder to which my application want to access(read/write) using NSOpenPanel.
When user selects the folder, I created the bookmark of selected folder path as bookmarked path in NSUserDefaults using NSURLBookmarkCreationWithSecurityScope.
NSOpenPanel *openDlg = [NSOpenPanel openPanel];
[openDlg setCanChooseDirectories:YES];
[openDlg setCanCreateDirectories:YES];
[openDlg setAllowsMultipleSelection:FALSE];
[openDlg setPrompt:@"Select"];
if ( [openDlg runModal] == NSModalResponseOK )
{
NSURL *url = openDlg.URL;
NSError *error = nil;
NSData *bookmark = [url
bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
includingResourceValuesForKeys:nil
relativeToURL:nil
error:&error];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:bookmark forKey:@"DOWNLOAD_FOLDER_BOOKMARK_PATH"];
[userDefaults synchronize];
}
Once you saved the bookmarked path in NSUserDefaults you can access the saved path later using NSURLBookmarkResolutionWithSecurityScope.
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSData * bookmarkedPathData = [userDefaults objectForKey:@"DOWNLOAD_FOLDER_BOOKMARK_PATH"];
NSURL* urlFromBookmark = [NSURL URLByResolvingBookmarkData:bookmarkedPathData
options:NSURLBookmarkResolutionWithSecurityScope
relativeToURL:nil
bookmarkDataIsStale:nil
error:&error];
Once you got the saved Bookmarked URL you can use that URL to perform read, write operation. Before reading/writing from/to the URL, please start the scope using [urlFromBookmark startAccessingSecurityScopedResource];
. And after finishing read/write operation stop the scope using [saveFolder stopAccessingSecurityScopedResource];
Note: I did tried to write to directly to Documents, Downloads, Desktop without creating folder inside these directories but Apple rejected the app, saying
Your application access the following locations 'Downloads'.
Then instead of writing directly to these directories( Documents, Downloads, Desktop), I asked the user to select(create & select) a folder, then performed the read/write operations on user selected folder using Security-Scope-Bookmark.
Hope this helps someone.