Search code examples
objective-ccocoaappstore-sandboxnspasteboard

NSServices : "How to create new file in Finder" with Sandbox App


I try to add a service to my application. This application has a service called, let's say, "MyService". I have a file in the Finder and I would like to copy that file with a new name at the same location. The user would right-click on the file and select MyService. A new file would appear with a new filename next to the original one. The problem is that my application is sandboxed. I can get the url of the file selected with :

- (NSPasteboardItem*)merge:(NSPasteboard *)pboard
 userData:(NSString *)userData error:(NSString **)error {
    NSArray* fileArray=[pboard propertyListForType:NSFilenamesPboardType];
}

My fileArray would contain the filepath. I can then change this filepath with the new filename. If I just create a new file using :

NSString *filePath = [filesArray objectAtIndex:0];
PDFDocument *PDF = [[PDFDocument alloc] initWithURL:[NSURL fileURLWithPath:filePath]];
NSURL *newFileUrl =[NSURL fileURLWithPath:newfilepath];
[PDF writeToURL:newFileURL];

I get an error! I know what I am doing is wrong but how to tell the Finder that the User did commit the action and so this action is secured in a way. How to tell this newFileURL is allowed? Thank you for your help


Solution

  • Sorry to say but not possible in sandbox. You'll have to ask the user for permission to create the new file. It would only work in the very specific case of just changing the file extension as described in Related items and here.

    Alternatively you could ask the user once for permission to write in the whole directory, store a Security Scoped Bookmark (SSB) and regain access on each launch of your app.

    EDIT: The Unarchiver from Mac App Store actually does it exactly this way, just tested. It publishes three NSServices called "Unarchive To Current Folder", "Unarchive To Desktop" and "Unarchive To...". They all ask for permission at least once.

    To ask for permission for a whole directory use a NSOpenPanel as in this answer and the appropriate properties setCanChooseDirectories:YES and setCanChooseFiles:NO then read and store URL with SSB.