Замените файл с помощью NSSavePanel в изолированном приложении

Я создаю NSSavePanel используя этот код:

NSSavePanel *savePanel = [NSSavePanel savePanel];
savePanel.delegate = self;

savePanel.directoryURL = ...;
savePanel.nameFieldStringValue = ...;

[savePanel beginSheetModalForWindow:self.window
                  completionHandler:^(NSInteger returnCode) {

if (returnCode == NSFileHandlingPanelOKButton) {

// the completion handler

}
}];

Если на панели сохранения пользователь выбирает уже существующий файл, появляется окно с предупреждением "" ХХХ "уже существует. Вы хотите заменить его?".

Если пользователь нажимает кнопку "Заменить", в обработчике завершения старый файл удаляется с removeItemAtPath:error: метод NSFileManager, а затем создается новый файл (на самом деле: он создается во временном местоположении, а затем перемещается с использованием moveItemAtPath:toPath:error: метод, но я думаю, что это просто деталь реализации):

if (returnCode == NSFileHandlingPanelOKButton) {
  // overwrite the url, because if we are here is because the user has already
  // expressed its willingness to overwrite the previous file
  NSError *error = nil;
  BOOL res = [[NSFileManager defaultManager] removeItemAtURL:savePanel.URL error:&error];

  if (res) {
    res = [[NSFileManager defaultManager] moveItemAtPath:tmpFilePath toPath:savePanel.URL error:&error];
  }

  // ...
}

В прошлом все всегда работало правильно. Однако сегодня я начал использовать Lion's Sandbox с правом "Чтение / запись".

С песочницей removeItemAtPath:error: успешно, но следующее moveItemAtPath:toPath:error: возвращает ошибку.

Это кажется разумным, потому что Powerbox дает мне права доступа (при чтении и записи) к файлу. Когда я удаляю этот файл, предоставленное мне право исчерпывается.

Правильно ли мое предположение?

Как я могу решить эту проблему?

2 ответа

Решение

Проблема в том, что после удаления файла ваши права на этот файл также исчезают. Вместо этого вам нужно перезаписать файл, например, используя [[NSFileManager defaultManager] createFileAtPath:contents:attributes:], Документация NSFileManager заявляет следующее для этого метода:

Если файл уже существует по пути, этот метод перезаписывает содержимое этого файла, если текущий процесс имеет соответствующие права для этого.

Используя методы из NSData/NSMutableData также может быть полезным.

Используйте [NSFileHandle fileHandleForWritingToURL:error:] с последующим writeData: вызовы для перезаписи существующего файла. Этот метод работает для меня в изолированном приложении. Для нового файла просто создайте его с помощью метода NSFileManager createFileAtPath:contents:attribute: (с содержимым, установленным в nil, если содержимое не помещается в память), а затем используйте NSFileHandle для записи данных.

Если вы хотите перезаписать изображение с использованием основной графики, см. NSSavePanel, CGImageDestinationFinalize и OS X sandbox

Другие вопросы по тегам