应用沙盒设计指南说:
App Sandbox 的相关项目功能允许您的应用访问与用户选择的文件同名但扩展名不同的文件。此功能由两部分组成:应用程序的 Info.plist 文件中的相关扩展列表和告诉沙箱您在做什么的代码。
我的 Info.plist 定义了文件的文档类型.pnd
(用户选择的文件),以及文件的文档类型.bak
。文件的条目.bak
除其他属性外,还具有属性NSIsRelatedItemType = YES
。
当用户编写 .pnd 文件的新版本时,我正在尝试使用相关项将现有文件移动到备份文件(将 .pnd 后缀更改为 .bak 后缀)。该应用程序是沙盒的。我不精通沙盒。
我PasteurOrgManager
用作NSFilePresenter
原始文件和备份文件的类:
@interface PasteurOrgData : NSObject <NSFilePresenter>
. . . .
@property (readonly, copy) NSURL *primaryPresentedItemURL;
@property (readonly, copy) NSURL *presentedItemURL;
@property (readwrite) NSOperationQueue *presentedItemOperationQueue;
@property (readwrite) NSFileCoordinator *fileCoordinator;
. . . .
- (void) doBackupOf: (NSString*) path;
. . . .
@end
doBackupOf:
方法如下。请注意,它还设置了NSFilePresenter
属性:
- (void) doBackupOf: (NSString*) path
{
NSError *error = nil;
NSString *appSuffix = @".pnd";
NSURL *const pathAsURL = [NSURL URLWithString: [NSString stringWithFormat: @"file://%@", path]];
NSString *const baseName = [pathAsURL lastPathComponent];
NSString *const prefixToBasename = [path substringToIndex: [path length] - [baseName length] - 1];
NSString *const baseNameWithoutExtension = [baseName substringToIndex: [baseName length] - [appSuffix length]];
NSString *backupPath = [NSString stringWithFormat: @"%@/%@.bak", prefixToBasename, baseNameWithoutExtension];
NSURL *const backupURL = [NSURL URLWithString: [NSString stringWithFormat: @"file://%@", backupPath]];
// Move backup to trash — I am sure this will be my next challenge
// (it's a no-op now because there is no pre-existing .bak file)
[[NSFileManager defaultManager] trashItemAtURL: backupURL
resultingItemURL: nil
error: &error];
// Move file to backup
primaryPresentedItemURL = pathAsURL;
presentedItemURL = backupURL;
presentedItemOperationQueue = [NSOperationQueue mainQueue];
[NSFileCoordinator addFilePresenter: self];
fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter: self]; // error here
[self backupItemWithCoordinationFrom: pathAsURL
to: backupURL];
[NSFileCoordinator removeFilePresenter: self];
fileCoordinator = nil;
}
该backupItemWithCoordinationFrom:
方法完成繁重的工作,基本上:
[fileCoordinator coordinateWritingItemAtURL: from
options: NSFileCoordinatorWritingForMoving
error: &error
byAccessor: ^(NSURL *oldURL) {
[self.fileCoordinator itemAtURL: oldURL willMoveToURL: to];
[[NSFileManager defaultManager] moveItemAtURL: oldURL
toURL: to
error: &error];
[self.fileCoordinator itemAtURL: oldURL didMoveToURL: to];
}
但代码并没有那么远。我已经跟踪了代码,并且 URL 变量符合我的预期,并且是合理的。在上面代码中的“此处错误”处,我分配了 File Presenter,我得到:
NSFileSandboxingRequestRelatedItemExtension: an error was received from pboxd instead of a token. Domain: NSPOSIXErrorDomain, code: 1
[presenter] +[NSFileCoordinator addFilePresenter:] could not get a sandbox extension. primaryPresentedItemURL: file:///Users/cope/Me.pnd, presentedItemURL: file:///Users/cope/Me.bak
任何帮助表示赞赏。
(我已经阅读了相关的帖子Where can a sandboxed Mac app save files?以及为什么 NSFilePresenter 协议方法永远不会被调用?。我注意到其他几个似乎与此问题无关的沙盒相关帖子。)
MacBook Pro、MacOS 10.13.5、XCode 版本 9.3 (9E145)