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

2024-02-29

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

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

Code:

[[NSFileManager defaultManager] moveItemAtPath:currentPath 
                                        toPath:newPath error:&error]

Error:

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

我发誓这在昨天还有效,没有任何改变......(请参阅下面的更新)

反正。我假设,如果用户允许通过“打开”对话框或拖放访问文件,则应允许沙盒应用程序重命名该文件。

UPDATE:

我终于设法将其追溯到我的代码中的更改:

当我打电话时我可以重现错误NSFileCoordinator.item(at: newSrcUrl, willMoveTo: newDstUrl)在执行实际移动之前。如果我跳过这一步,一切都会再次正常运行,控制台中不会出现任何错误。

完整代码:

let coordinator = NSFileCoordinator()

coordinator.coordinate(writingItemAt: srcURL, options: .forMerging,
                       writingItemAt: dstURL, options: .forMerging) { newSrcUrl, newDstUrl in

    // Calling this first results in "could not get a sandbox extension" error in console:
    //coordinator.item(at: newSrcUrl, willMoveTo: newDstUrl)

    try moveItem(at: newSrcUrl, to: newDstUrl)

    coordinator.item(at: newSrcUrl, didMoveTo: newDstUrl)
}

item(at oldURL: URL, willMoveTo newURL: URL)似乎是在更改文档的文件扩展名(例如 .rtf 到 .rtfd)时使用的,但我的应用程序并非如此。仅文件名发生变化,文件扩展名不变。我认为最好的做法是致电will/didMove方法,不过貌似有副作用。

回顾一下,我的应用程序所做的就是要求用户打开一个文件夹(通过NSOpenPanel所以我的应用程序获得写入该文件夹的权限),然后我的应用程序在该文件夹中创建一个文件,然后重命名它。


您面临的问题不是关于持久化任何内容,而是关于沙箱如何工作:

规则是……

To rename一个文件(实际上执行移动操作),
您需要对该文件的父目录具有写入权限。

我们的问题是……

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

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

那么我们该怎么办 ?

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

现在我已经阅读了有关沙箱的文档,我注意到NS文件协调器有一个方法叫做itemAtURL:willMoveToURL: http://developer.apple.com/library/mac/#documentation/Foundation/Reference/NSFileCoordinator_class/Reference/Reference.html#//apple_ref/occ/instm/NSFileCoordinator/itemAtURL%3awillMoveToURL%3a

这让我想到了这个小snippet https://gist.github.com/aquarius/a1086ed57b26cb292160(我在这里重写是因为它缺少 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];
    }
}];

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

NSFileSandboxingRequestRelatedItemExtension: an error was received from pboxd instead of a token. Domain: NSPOSIXErrorDomain, code: 1

耶,苹果,耶

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

应用程序沙箱:重命名文件不起作用 的相关文章

随机推荐