Чтение файлов с внешнего хранилища в iOS 13 - PullRequest
4 голосов
/ 03 марта 2020

У меня есть приложение iOS, которое пытается прочитать файлы с внешнего устройства хранения, не импортируя их в изолированную программную среду приложения.

Для этого я следовал приведенным здесь документам Apple -

Предоставление доступа к каталогам

Я могу извлечь выбранный каталог (который находится на внешнем устройстве хранения данных, подключенном через порт Lightning) и перечислить файлы внутри каталога.

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

        let shouldStopAccessing = pickedFolderURL.startAccessingSecurityScopedResource()
        defer {
          if shouldStopAccessing {
            pickedFolderURL.stopAccessingSecurityScopedResource()
          }
       }
       var coordinatedError:NSError?
       NSFileCoordinator().coordinate(readingItemAt: pickedFolderURL, error: &coordinatedError) { (folderURL) in
        let keys : [URLResourceKey] = [.isDirectoryKey]
        let fileList = FileManager.default.enumerator(at: pickedFolderURL, includingPropertiesForKeys: keys)!
        for case let file as URL in fileList {
            if !file.hasDirectoryPath {
                do {
                    // Start accessing a security-scoped resource.
                    guard file.startAccessingSecurityScopedResource() else {
                        // Handle the failure here.
                        //THIS ALWAYS FAILS!!
                        return
                    }

                    // Make sure you release the security-scoped resource when you are done.
                    defer { file.stopAccessingSecurityScopedResource() }

Я должен добавить, что это работает просто отлично, если файлы находятся на iCloud Drive через симулятор. Он не работает как на внешних устройствах, так и на iCloud Drive на реальном устройстве.

Здесь - это полноценный рабочий проект, демонстрирующий сбой.

  1. При запуске на симуляторе доступ к файлам iCloud Drive просто прекрасен. Но запустить на устройстве не удается.
  2. Не удается запустить устройство для доступа к USB-накопителю.

1 Ответ

3 голосов
/ 09 марта 2020

Итак, это похоже на проблему с документацией по ссылке, размещенной выше. Когда пользователь выбирает папку, все файлы и папки получают рекурсивный доступ и автоматически ограничиваются областью безопасности. Строка guard file.startAccessingSecurityScopedResource() всегда возвращает false.

Хитрость в получении этой работы состоит не в том, чтобы пытаться защитить отдельные файлы в области видимости, а в том, чтобы этот фрагмент кода не выполнялся ДО того, как вы получите доступ к файлам.

   defer {
      if shouldStopAccessing {
        pickedFolderURL.stopAccessingSecurityScopedResource()
      }
   }

Пока вы продолжаете получать доступ к файлам, пока pickedFolderURL находится в области безопасности, вы будете успешны.

Надеюсь, это кому-нибудь поможет.

...