web-dev-qa-db-fra.com

Création de document UID sur iOS 11: le lecteur n'est pas autorisé à accéder à l'URL

Depuis iOS 11, j'ai rencontré l'erreur suivante à chaque fois que je crée un nouveau document à l'aide de l'API UIDocument:

[ERREUR] Impossible d'obtenir les valeurs d'attribut pour l'élément /var/mobile/Containers/Data/Application/XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX/Documents/myDoc-XXXXXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXXXXXXXX.myFile ( n).

Erreur: Domaine d'erreur = Code NSFileProviderInternalErrorDomain = 1
"Le lecteur n'est pas autorisé à accéder à l'URL."
UserInfo = {NSLocalizedDescription = Le lecteur n'est pas autorisé à accéder à l'URL.}

Contrairement aux questions similaires ( 1 , 2 , 3 ) sur SO, je n'utilise pas UIDocumentBrowserViewController. Je crée simplement un UIDocument et appelle moi-même save() dans le répertoire Documents. La question la plus proche J'ai trouvé utilise UIManagedDocument. Cependant, dans mon cas, le fichier est toujours créé et écrit avec succès malgré le message d'erreur.

Voici l'essentiel de ma routine de sauvegarde:

@IBAction func createDoc(_ sender: Any) {
    let uuid = UUID().uuidString
    let doc = Document(baseName: "myDoc-\(uuid)")
    doc.save(to: doc.fileURL, for: .forCreating) { (completed) in
        if (completed) {
            doc.close(completionHandler: nil)
            self.verifyNumberOfFiles()
        }
    }
}

Ma sous-classe UIDocument est également presque vide pour la simplicité de cette question:

class Document: UIDocument {    

    let fileExtension = "myFile"

    override init(fileURL url: URL) {
        super.init(fileURL: url)
    }

    /// Convenience method for `init(fileURL:)`
    convenience init(baseName: String) {
        self.init(fileURL: documentsDirectory.appendingPathComponent(baseName).appendingPathExtension(Document.fileExtension))
    }

    override func contents(forType typeName: String) throws -> Any {
        return NSData()
    }

    override func load(fromContents contents: Any, ofType typeName: String?) throws {

    }

}

J'écris toujours dans le dossier Documents, et ma routine de recherche peut vérifier que mes fichiers ont bien été créés:

public var documentsDirectory: URL {
    return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last!
}

func loadFileURLs(from dirURL: URL) -> [URL]? {
    return try? FileManager().contentsOfDirectory(at: dirURL, includingPropertiesForKeys: nil)
}

Ce que j'ai découvert jusqu'à présent:

  • L'erreur apparaît même lorsque j'ai déjà configuré mon UTI. Voir ceci et ceci .
  • Je peux vérifier que mon UTI fonctionne lorsque j'envoie un "myFile" à mon appareil via AirDrop et que mon application se déclenche correctement.
  • L'erreur n'apparaît que sur iOS 11. Le même code ne reproduit pas l'erreur sur iOS 10, comme dans la question ci-dessus .
  • J'ai essayé d'ajouter la clé UISupportsDocumentBrowser bien que je n'utilise pas le navigateur, mais cela ne dissout pas l'erreur.

Qu'est-ce qui se passe? Est-ce juste un message d'erreur "bruit" sur iOS 11?

Voici ???? mon code GitHub en ligne si quelqu'un est intéressé.

11
HuaTham

Une solution de contournement consiste à créer le fichier en enregistrant ses données sur le disque, puis à l'ouvrir comme vous le feriez avec un fichier existant.

Votre méthode createDoc(_:) aimerait alors ceci:

@IBAction func createDoc(_ sender: Any) {
  let uuid = UUID().uuidString
  let baseName = "myDoc-\(uuid)"
  let url = documentsDirectory
      .appendingPathComponent(baseName)
      .appendingPathExtension(Document.fileExtension)

  do {
    let emptyFileData = Data()
    try emptyFileData.write(to: url)
    let document = Document(fileURL: url)
    document.open() { completed in
      guard completed else { 
        // handle error
        return 
      }
      doc.close(completionHandler: nil)
      self.verifyNumberOfFiles() 
    }
  } catch {
    // handle error
  }
}
3
Adrian Schönig

Dans Xcode 9.3, il est possible de spécifier un nouvel élément dans info.plist: 

Prise en charge du navigateur de documents (YES)

Cela permet d'accéder au répertoire de documents de l'application (par exemple,/var/mobile/Containers/Data/Application/3C21358B-9E7F-4AA8-85A6-A8B901E028F5/Documents sur un périphérique). Développeur Apple doc ici .

0
paul.lander