应用程序沙箱:重命名文件不起作用

Mar*_*ark 5 cocoa mac-app-store appstore-sandbox

我有一个基本的Cocoa应用程序,可以让用户管理文件列表。通过拖放添加文件,并且在应用程序重新启动期间,我将访问权限保留在安全的书签中。

到目前为止,一切都很好。允许该应用读取和写入用户的文件,但是重命名失败并出现权限错误,声称不允许我的应用访问父文件夹。

码:

[[NSFileManager defaultManager] moveItemAtPath:currentPath 
                                        toPath:newPath error:&error]
Run Code Online (Sandbox Code Playgroud)

错误:

Error Domain=NSCocoaErrorDomain Code=513 "“Some image.jpg” couldn’t 
be moved because you don’t have permission to access “some folder”
Run Code Online (Sandbox Code Playgroud)

我发誓这只在昨天才起作用,但没有任何变化。我假设如果用户允许通过“打开”对话框访问文件或拖放文件,则应允许沙盒应用程序重命名文件。

Nig*_*lve 5

您面临的问题不在于坚持任何东西,而在于沙箱的工作方式:

规则是……

重命名文件(实际上是执行移动操作),
您需要对该文件的父目录具有写入权限。

我们的问题是……

如果您拖动文件,沙箱只会扩展对这些文件的访问权限,而不是它们的父目录,因此此错误表明它需要权限

现在,尝试拖动包含这些文件的文件夹,您会发现一切正常:)

那么我们该怎么办 ?

一个简单的解决方案是要求用户通过 NSOpenPanel 选择一个“工作”目录,这样沙箱就可以访问,而不会在用户每次希望重命名时疏远他
但是我们现在正在打扰用户他甚至不应该知道的废话大约在第一位!
所以对我来说这是糟糕的设计/用户体验

现在我已经阅读了关于沙箱的文档,我注意到NSFileCoordinator有一个名为itemAtURL:willMoveToURL的方法

Wich 把我带到了这个小片段 (我在这里重写是因为它缺少 willMove 函数)
我们想要在这里做的是为了重命名而请求一个沙箱扩展:

NSURL *sourceURL = document.fileURL;
NSURL *destinationURL = [[sourceURL URLByDeletingLastPathComponent] URLByAppendingPathComponent:fileName isDirectory:NO];

NSError *writeError = nil;
__block NSError *moveError = nil;
__block BOOL success = NO;

NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];

[coordinator coordinateWritingItemAtURL:sourceURL
                                options:NSFileCoordinatorWritingForMoving
                       writingItemAtURL:destinationURL
                                options:NSFileCoordinatorWritingForReplacing
                                  error:&writeError
                             byAccessor:^(NSURL *newURL1, NSURL *newURL2)
{
    NSFileManager *fileManager = [NSFileManager new];

    [coordinator itemAtURL:sourceURL willMoveToURL:destinationURL];

    success = [fileManager moveItemAtURL:newURL1 toURL:newURL2 error:&moveError];

    if (success)
    {
        [coordinator itemAtURL:newURL1 didMoveToURL:newURL2];
    }
}];
Run Code Online (Sandbox Code Playgroud)

可悲的是,此方法似乎仅针对更改文件扩展名而不是重命名,因此日志中出现此错误:

NSFileSandboxingRequestRelatedItemExtension: an error was received from pboxd instead of a token. Domain: NSPOSIXErrorDomain, code: 1
Run Code Online (Sandbox Code Playgroud)

耶,苹果,耶