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

时间:2012-12-19 10:38:55

标签: cocoa mac-app-store appstore-sandbox

我有一个基本的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”

我发誓这曾经在昨天工作,没有任何改变......无论如何。我假设如果用户允许通过“打开”对话框或拖放操作来访问文件。删除应该允许沙盒应用程序重命名文件。

2 个答案:

答案 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];
        }
    }];
相关问题