directorysandboxnsopenpanel

remember user selected folder and reopen it by NSOpenPanel under Sandbox


Apple review require my app to remember the folder that user selected last time. But I can not make it under Sandbox. the -setDirectoryURL seems not working under Sandbox. What should I do? Thank you for your help!

// read string saveFolder from NSUserDefaults
NSOpenPanel * myPanel = [NSOpenPanel openPanel];
[myPanel setTitle:@"Select Output Folder"];
[myPanel setCanChooseDirectories:YES];
[myPanel setCanCreateDirectories:YES];
[myPanel setAllowsMultipleSelection:NO];
[myPanel setCanChooseFiles:NO];

NSLog(@"before openpanel:folder=%@",saveFolder); // <== return normal
[myPanel setDirectoryURL:[NSURL URLWithString:saveFolder.stringValue]];
NSLog(@"readback:folder=%@",[[myPanel URL] path]); // <== return nil here

if ([myPanel runModal] == NSOKButton)
{
    //  
    saveFolder = [[myPanel URL] path]];
    // then save the saveFolder string to NSUserDefaults
    //
}

Solution

  • it seems we should add and use this entitlement:

    com.apple.security.files.bookmarks.app-scope

    SAVE THE URL:

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSError *error = nil;
    NSData *bookmarkData = [[myPanel URL] bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope includingResourceValuesForKeys:nil relativeToURL:nil error:&error];
    if (!error)
    {
        [defaults setObject:bookmarkData forKey:@"iData"];
        [defaults synchronize];
    }
    

    READ BACK:

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    bookmarkFileURL = nil;
    NSData *bookmarkData = [defaults objectForKey:@"iData"];
    if (bookmarkData != nil)
    {
        NSError *error=nil;
        bookmarkFileURL = [NSURL URLByResolvingBookmarkData:bookmarkData options:NSURLBookmarkResolutionWithSecurityScope relativeToURL:nil bookmarkDataIsStale:nil error:&error];
        if (error != nil) bookmarkFileURL = nil;
    }
    if (bookmarkFileURL)
    {
        [bookmarkFileURL startAccessingSecurityScopedResource];
    }
    //
    //
    [bookmarkFileURL stopAccessingSecurityScopedResource];