В руководстве по разработке App Sandbox написано:
Функция связанных элементов App Sandbox позволяет вашему приложению получать доступ к файлам
которые имеют то же имя, что и выбранный пользователем файл, но отличаются
расширение. Эта функция состоит из двух частей: список связанных
расширения в файле Info.plist приложения и код, чтобы сообщить
песочница что ты делаешь.
Мой Info.plist определяет тип документа для .pnd
файлов (выбранный пользователем файл), а также тип документа для .bak
файлов. Запись для файлов .bak
имеет, помимо прочего, свойство NSIsRelatedItemType = YES
.
Я пытаюсь использовать Связанные элементы для перемещения существующего файла в файл резервной копии (измените суффикс .pnd на суффикс .bak), когда пользователь записывает новую версию файла .pnd. Приложение находится в песочнице. Я не опытный в песочнице.
Я использую 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
Любая помощь приветствуется.
(Я прочитал похожие посты Где в песочнице приложение Mac может сохранять файлы? и Почему никогда не вызываются методы протокола NSFilePresenter? . Я обратил внимание на несколько других песочниц - похожие посты, которые не имеют отношения к данной проблеме.)
MacBook Pro, MacOS 10.13.5, версия XCode 9.3 (9E145)