Каков правильный способ обработки устаревших закладок NSURL?

18

При разрешении NSURL из закладки с защищенной областью, если пользователь переименовал или переместил этот файл или папку, закладка будет устаревать. В документе Apple говорится об этом:

  

isStale

     

При возврате, если ДА, данные закладки устаревают. Ваше приложение должно   создать новую закладку с использованием возвращаемого URL-адреса и использовать ее вместо   любые сохраненные копии существующей закладки.

К сожалению, это редко работает для меня. Он может работать в 5% случаев. Попытка создать новую закладку с использованием возвращаемого URL приводит к ошибке, код 256 и поиск в консоли показывает сообщение из sandboxd, в котором говорится о запрете чтения файлов на обновленном URL-адресе.

Примечание Если регенерация закладки работает, она работает только при первом восстановлении. Кажется, никогда не работает, если папка / файл будет перемещаться / переименовываться снова.

Как я изначально создаю & amp; сохранить закладку

-(IBAction)bookmarkFolder:(id)sender {
  _openPanel = [NSOpenPanel openPanel];
  _openPanel.canChooseFiles = NO;
  _openPanel.canChooseDirectories = YES;
  _openPanel.canCreateDirectories = YES;
  [_openPanel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {
    if (_openPanel.URL != nil) {
      NSError *error;
      NSData *bookmark = [_openPanel.URL bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
                                  includingResourceValuesForKeys:nil
                                                   relativeToURL:nil
                                                           error:&error];
      if (error != nil) {
        NSLog(@"Error bookmarking selected URL: %@", error);
        return;
      }
      NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
      [userDefaults setObject:bookmark forKey:@"bookmark"];
    }
  }];
}

Код, разрешающий закладку

-(void)resolveStoredBookmark {
  NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
  NSData *bookmark = [userDefaults objectForKey:@"bookmark"];
  if (bookmark == nil) {
    NSLog(@"No bookmark stored");
    return;
  }
  BOOL isStale;
  NSError *error;
  NSURL *url = [NSURL URLByResolvingBookmarkData:bookmark
                                         options:NSURLBookmarkResolutionWithSecurityScope
                                   relativeToURL:nil
                             bookmarkDataIsStale:&isStale
                                           error:&error];
  if (error != nil) {
    NSLog(@"Error resolving URL from bookmark: %@", error);
    return;
  } else if (isStale) {
    if ([url startAccessingSecurityScopedResource]) {
      NSLog(@"Attempting to renew bookmark for %@", url);
      // NOTE: This is the bit that fails, a 256 error is 
      //       returned due to a deny file-read-data from sandboxd
      bookmark = [url bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
               includingResourceValuesForKeys:nil
                                relativeToURL:nil
                                        error:&error];
      [url stopAccessingSecurityScopedResource];
      if (error != nil) {
        NSLog(@"Failed to renew bookmark: %@", error);
        return;
      }
      [userDefaults setObject:bookmark forKey:@"bookmark"];
      NSLog(@"Bookmark renewed, yay.");
    } else {
      NSLog(@"Could not start using the bookmarked url");
    }
  } else {
    NSLog(@"Bookmarked url resolved successfully!");
    [url startAccessingSecurityScopedResource];
    NSArray *contents = [NSFileManager.new contentsOfDirectoryAtPath:url.path error:&error];
    [url stopAccessingSecurityScopedResource];
    if (error != nil) {
      NSLog(@"Error reading contents of bookmarked folder: %@", error);
      return;
    }
    NSLog(@"Contents of bookmarked folder: %@", contents);
  }
}

Когда закладка устарела, результирующий разрешенный URL указывает на правильное местоположение, я просто не могу получить доступ к файлу, несмотря на то, что [url startAccessingSecurityScopedResource] возвращает YES.

Возможно, я неверно истолковал документацию относительно устаревших закладок, но я надеюсь, что я просто делаю что-то глупое. Появление NSOpenPanel каждый раз, когда файл / папка с закладками переименовывается или перемещается, мой единственный вариант на данный момент кажется смешным.

Я должен добавить, что у меня есть com.apple.security.files.bookmarks.app-scope , com.apple.security.files.user-selected.read-write и com.apple.security.app-sandbox все установлены в true в моем файле прав.

    
задан George 30.05.2014 в 14:28
источник

1 ответ

14

После многих неутешительных испытаний я пришел к следующим выводам. Хотя логично, они разочаровывают, поскольку полученный опыт для пользователей далек от идеала и значительная боль для разработчиков в зависимости от того, насколько они готовы пойти, чтобы помочь пользователям восстановить ссылки на закладки.

Когда я говорю «обновить» ниже, я имею в виду «сгенерируйте новую закладку, чтобы заменить устаревшую закладку, используя URL-адрес, разрешенный из устаревшей закладки».

  1. Обновление всегда работает до тех пор, пока ресурс с закладками перемещается или переименовывается в каталог, к которому у вашего приложения уже разрешено доступ. Таким образом, по умолчанию он всегда работает в папке контейнера вашего приложения.

  2. Обновление завершается с ошибкой, если ресурс с закладками перемещается в папку, в которой ваше приложение не имеет доступа к доступу. например Пользователь перетаскивает папку из папки вашего контейнера в какую-либо папку вне папки контейнера. Вы сможете разрешить URL-адрес, но не получить доступ и не обновить закладку.

  3. Возобновление завершается с ошибкой, если ресурс с закладками находится в папке, к которой у вашего приложения нет доступа, и затем переименовывается. Это означает, что пользователь может явно предоставить вашему приложению доступ к ресурсу, а затем непреднамеренно отменить этот доступ, просто переименовав его.

  4. Ошибка разрешения, если ресурс перемещен на другой том. Не уверен, что это ограничение закладок вообще или просто при использовании в изолированном приложении.

Для вопросов 2 & amp; 3 вы находитесь в приличном положении как разработчик, так как разрешение URL с закладками действительно работает. Вы можете, по крайней мере, привести пользователя, указав им, какие ресурсы им необходимы, чтобы предоставить доступ к вашему приложению и где они находятся. Опыт может быть улучшен путем выбора папки, содержащей (прямо или косвенно) все ресурсы, необходимые для обновления закладки. Это может быть даже объем, который полностью решает проблему, если они готовы предоставить вашему приложению такой доступ.

В вопросе 4 разрешение не работает вообще. Пользователь должен будет перемещать файл без каких-либо намеков, так как вы не можете разрешить новое местоположение. Одна вещь, которую я сделал в своем текущем приложении, которая уменьшила боль этой проблемы, заключается в добавлении расширенного атрибута к любому ресурсу, в котором я храню закладку. Выполнение этого, по крайней мере, позволяет мне выбрать папку для поиска ранее связанных ресурсов.

Разочарование ограничений, но закладки по-прежнему выигрывают от хранения статических путей.

    
ответ дан George 11.08.2014 в 18:01
  • @ user362515 Просто для подтверждения, вы говорите, что не видите никаких проблем с 10.11 при создании новой закладки, когда старый разрешает, но отчеты как устаревшие и недоступны? В частности, номер пули 2 больше не является проблемой? Если да, это здорово! –  George 01.11.2015 в 16:22
  • Начиная с OS X 10.11 Кажется, нет проблем с созданием новой закладки с защищенной областью из старой. –  user362515 01.11.2015 в 16:23
  • Да, пока startAccessingSecurityScopedResource запускается в новой закладке в течение времени bookmarkDataWithOptions. И BTW около 4) - Закладка разрешения переименованных / перемещенных файлов работает только на том же томе, это документировано. –  user362515 01.11.2015 в 16:26
  • @ user362515 Удивительно, по крайней мере, это некоторое улучшение. Я не вижу в документации, где говорится, что разрешение работает только на исходном томе. Я вижу, где он говорит, что это не удастся для тома, который не может быть установлен, конечно. У вас есть ссылка на то, где вы видите это? –  George 01.11.2015 в 17:40
  • Я действительно создал отдельный вопрос, связанный с этим stackoverflow.com/questions/33464056/... –  user362515 01.11.2015 в 18:05
Показать остальные комментарии