Неудачная попытка использования связанных элементов для создания файла резервной копии в изолированном приложении - PullRequest
0 голосов
/ 01 июля 2018

В руководстве по разработке 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)

...