NSSavePanel is not saving a file after sandboxing an app

此生再无相见时 提交于 2019-12-05 20:54:27

问题


I'm having a problem saving a string file with NSSavePanel after sandboxing the app for the Mac App Store. I set com.apple.security.files.user-selected.read-write to YES and the NSOpenPanel is working as it should.

When I try to save a new file, though, it seems that everything is working fine but then there is no saved file where it should be....

This is the code I am using to save the file:

NSSavePanel *save = [NSSavePanel savePanel];

long int result = [save runModal];

if (result == NSOKButton)
{
    NSString *selectedFile = [save filename];
    NSString *fileName = [[NSString alloc] initWithFormat:@"%@.dat", selectedFile];
    NSString *arrayCompleto = [[NSString alloc]initWithFormat:@"bla bla bla"];
    [arrayCompleto writeToFile:fileName
                    atomically:NO
                      encoding:NSUTF8StringEncoding
                         error:nil];
}

回答1:


First of all, the -[NSSavePanel filename] selector has been deprecated. Use -[NSSavePanel URL] instead. Second, the way that the -[NSString writeToFile:atomically:encoding:error] tells you what you're doing wrong is with the error:(NSError**) argument.

You should also handle errors for file I/O in particular, because even if your code is 100% correct, there still might be errors on the user's system (insufficient privileges, etc.) and presenting the error to the user will allow them to see it failed (and have some idea why). Handling the error in code will also allow your app to recover. For instance, if you tried to read in the file below the code you pasted (after writing it to disk), but the user tried writing it to a network share they didn't have access to, your app might crash. If you know the write failed, you can proceed accordingly (perhaps prompting for a different save location).

In this case, though, I believe the following line is your problem:

NSString *fileName = [[NSString alloc] initWithFormat:@"%@.dat", selectedFile];

When your app is sandboxed, the user needs to give you permission for either a specific file or a specific directory through the open/save panels to bring them into your sandbox. What you're doing is taking the file the user gave you permission to write and saying "that's great, but I want to save a different file", which violates the sandbox. What you should do instead is set the extension in the Save Panel. The complete fixed solution would be:

NSSavePanel *save = [NSSavePanel savePanel];
[save setAllowedFileTypes:[NSArray arrayWithObject:@"dat"]];
[save setAllowsOtherFileTypes:NO];

NSInteger result = [save runModal];

if (result == NSOKButton)
{
     NSString *selectedFile = [[save URL] path];
     NSString *arrayCompleto = @"bla bla bla";

     NSError *error = nil;
     [arrayCompleto writeToFile:selectedFile
                     atomically:NO
                       encoding:NSUTF8StringEncoding
                          error:&error];
}

if (error) {
    // This is one way to handle the error, as an example
    [NSApp presentError:error];
}

If in the future something else is wrong, you can check the value of error at runtime. While debugging, set a breakpoint inside the if (error) statement to check error object's value (do a po error in Xcode's debugger). That should help you figure out what's wrong.



来源:https://stackoverflow.com/questions/10708845/nssavepanel-is-not-saving-a-file-after-sandboxing-an-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!