应用程序沙箱设计指南说:
App的相关项功能允许您的应用程序访问与用户选择的文件相同的文件,但扩展名不同。这个特性由两个部分组成:应用程序的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;
. . . .
@enddoBackupOf:方法如下所示。注意,它还设置了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变量和我所期望的一样,并且是合理的。在上面代码中的"error here“(我分配了文件演示者)的点上,我得到:
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?和Why do NSFilePresenter protocol methods never get called?的相关帖子。我注意到了其他几个与沙箱有关的帖子,这些帖子似乎与这个问题无关。)
MacBook Pro,MacOS 10.13.5,XCode版本9.3 (9E145)
发布于 2021-06-06 19:09:39
不要读太多关于避免沙箱的文章。大多数解释离最明显的问题太远了。他们没有解释正确触发沙箱的陷阱,而是解释了如何完全避免沙箱。这不是一个解决方案--它是一根线!
因此,最明显的问题是,在转换到NSURL**.**之前,仍然需要在字符串中正确转义字符的pasteboard公开。
因此,以file://“开头的NSString应该使用类似..。
NSString *encodeStringForURL = [yourstring stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];在转换为NSURL之前,
NSURL *fileurl = [NSURL URLWithString:encodeStringForURL];
NString *output = fileurl.absoluteString;https://stackoverflow.com/questions/51121960
复制相似问题