我有一个基本的Cocoa应用程序,让用户可以管理文件列表。文件通过拖放和添加; drop,我会在应用程序重新启动时将访问权限保留在安全书签中。
到目前为止一切顺利。该应用程序可以读取和写入用户的文件,但重命名失败,并显示权限错误,声称我的应用程序不允许访问父文件夹。
代码:
[[NSFileManager defaultManager] moveItemAtPath:currentPath
toPath:newPath error:&error]
错误:
Error Domain=NSCocoaErrorDomain Code=513 "“Some image.jpg” couldn’t
be moved because you don’t have permission to access “some folder”
我发誓这曾经在昨天工作,没有任何改变......无论如何。我假设如果用户允许通过“打开”对话框或拖放操作来访问文件。删除应该允许沙盒应用程序重命名文件。
答案 0 :(得分:3)
你面临的问题不是坚持任何事情,而是关于沙盒如何运作:
规则是......
重命名文件(实际上执行移动操作),
您需要具有对所述文件的父目录的写入权限。
我们的问题是......
如果您拖动文件,沙箱将仅扩展对这些文件的访问权限,而不是其父目录,因此此错误表明它需要权限
现在,尝试拖动包含这些文件的文件夹,您会发现一切正常:)
那我们该怎么办?
一个简单的解决方案是让用户通过NSOpenPanel选择一个“工作”目录,这样沙盒就可以访问,而不会在每次希望重命名时疏远用户。 但是我们现在正在困扰用户,因为他一开始就不应该知道垃圾! 所以对我来说这是糟糕的设计/ ux
现在我已经阅读了有关沙盒的文档,我注意到 NSFileCoordinator 有一个名为itemAtURL:willMoveToURL:的方法
我带领我去了这个小snippet(我在这里重写了,因为它缺少了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
Yay,apple,yay
答案 1 :(得分:2)
以下内容适用于我只要我在myext
中添加Info.plist
作为相关项目文档类型。这在Apple's Documentation中注明
这是一段摘录:
在这两种情况下,您必须对应用程序的Info.plist文件进行少量更改。您的应用程序应该已经声明了一个文档类型(CFBundleDocumentTypes)数组,该数组声明了您的应用程序可以打开的文件类型。
对于该数组中的每个文件类型字典,如果该文件类型应被视为用于打开和保存目的的潜在相关类型,请添加键值NSIsRelatedItemType,其布尔值为YES。
从BenRhayader的回答修改代码:
NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
NSURL *sourceURL = chosenFile;
NSURL *destinationURL = [chosenFile URLByAppendingPathExtension: @"myext"];
[coordinator coordinateWritingItemAtURL:sourceURL
options:NSFileCoordinatorWritingForMoving
writingItemAtURL:destinationURL
options:NSFileCoordinatorWritingForReplacing
error:NULL
byAccessor:^(NSURL *newURL1, NSURL *newURL2)
{
NSFileManager *fileManager = [NSFileManager new];
[coordinator itemAtURL:sourceURL willMoveToURL:destinationURL];
NSError *moveError;
BOOL success = [fileManager moveItemAtURL:newURL1 toURL:newURL2 error:&moveError];
if (success)
{
[coordinator itemAtURL:newURL1 didMoveToURL:newURL2];
}
}];