Question

I use this code to tell my second class to save a file to the given path :

if ([defaults boolForKey:@"SaveAutomatically"]) {
        basepath = [defaults objectForKey:@"SaveAutomaticallyPath"];
        basepath = [basepath stringByAppendingPathComponent:[defaults objectForKey:@"SaveAutomaticallyName"]];
}
[NSThread detachNewThreadSelector:@selector(saveTo:) toTarget:controller withObject:basepath];

So, the saveTo: method is called. It first checks if the given path is okay

if (![[[aPath pathExtension] lowercaseString] isEqualToString:@"icns"]) {
    aPath = [aPath stringByAppendingPathExtension:@"icns"];
}

if ([[NSFileManager defaultManager] fileExistsAtPath:aPath]) {
    [delegate error:@"File exists already."];
    [self performSelectorOnMainThread:@selector(fs)
                           withObject:nil waitUntilDone:NO];
}

Then it does some stuff and creates a CGImageDestinationRef :

NSURL *fileURL = [NSURL fileURLWithPath:aPath];
CGImageDestinationRef dr = CGImageDestinationCreateWithURL((CFURLRef)fileURL, kUTTypeAppleICNS , count, NULL);
if (!dr) {
    [delegate error:@"Unable to save icon file."];
    [self performSelectorOnMainThread:@selector(fs)
                           withObject:nil waitUntilDone:NO];
    return;
}

dr is nil every time. If I give the saveTo a path by using a NSSavePanel it does not complain and works fine. I tried logging the path in saveTo: but that works fine (eg. /Users/Home/Desktop/Result.icns).

In other words, when the above code saves to /Users/Home/Desktop/Result.icns it fails, but when I let the user decide to save to that same path using an NSSavePanel, there's no problem.

I'm using SandBoxing. How can I solve this?

Was it helpful?

Solution

A sandboxed app has no file access, outside of its own container folder, unless the user expressly permits it using the Open/Save Panel or via drag-and-drop. You will need to allow the user to choose the path they wish to save to and keep a security-scoped bookmark of that folder for later use (i.e. if you want to update that file after the app has restarted).

Here is a quote from Apple's Sandbox Design Guide:

Your sandboxed app can access file system locations outside of its container in the following three ways:

  • At the specific direction of the user
  • By using entitlements for specific file-system locations (described in “Entitlements and System Resource Access”)
  • When the file system location is in certain directories that are world readable
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top