5

I have a basic Cocoa app that let's the user manage a list of files. Files are added via drag & drop and I persist the access permissions in a secure bookmark across application restarts.

So far so good. The app is allowed to read and write to the user's files, but renaming fails with a permission error claiming that my app is not allowed to access the parent folder.

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”

I swear that this used to work just yesterday, nothing changed... (see update below)

Anyway. I would assume that if a user allows access to a file via an Open dialog or drag & drop that a sandboxed application should be allowed to rename the file.

UPDATE:

I finally managed to track this down to a change in my code:

I can reproduce the error when I call NSFileCoordinator.item(at: newSrcUrl, willMoveTo: newDstUrl) before performing the actual move. If I skip this step, everything works again without any errors in the console.

The full code:

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) seems to be intended when changing the document's filename extension (e.g. .rtf to .rtfd), which is not the case for my app. Only the file name changes, not the file extension. I figured it would be best practice to call the will/didMove methods, but looks like there are side effects.

To recap, all my app does is to ask the user to open a folder (via NSOpenPanel so my app gets permission to write to that folder), then my app creates a file in that folder and later on renames it.

4

2 回答 2

5
于 2013-04-06T13:03:43.373 回答
2

只要我在myext我的Info.plist. 这在Apple 的文档中有所说明。
这是一段摘录:

在这两种情况下,您都必须对应用程序的 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];
        }
    }];
于 2013-05-03T15:04:51.453 回答