16 votes

Bonne façon de gérer le dossier Documents/Boîte de réception dans une application iOS

Lorsqu'un fichier est passé dans une application iOS par le système d'interaction des documents, une copie du fichier est stockée dans le dossier Documents/Inbox du bundle de l'application. Après que l'application ait traité le fichier, il est évident qu'elle doit supprimer le fichier de Documents/Inbox, sinon le dossier continuera de croître et gaspillera de l'espace de stockage sur le périphérique.

Cette solution simple (A) me met mal à l'aise, cependant, car mon application doit interagir avec l'utilisateur avant de finir le traitement et la suppression du fichier. Si l'utilisateur suspend l'application pendant cette période d'interaction, et que l'application est ensuite arrêtée alors qu'elle est en arrière-plan, le fichier obsolète ne sera pas supprimé lorsque l'application redémarrera la prochaine fois. Bien sûr, je peux améliorer mon application pour couvrir ce scénario, mais je crains qu'il y aura toujours un autre cas limite qui laissera un dossier Documents/Inbox "non propre".

Une solution préférable (B) serait donc de supprimer le dossier Documents/Inbox à un moment approprié (par exemple, lorsque l'application se lance normalement, c'est-à-dire non via l'interaction des documents). Cela me met encore mal à l'aise car j'accéderais à un chemin de système de fichiers dont l'emplacement n'est documenté nulle part officiellement. Par exemple, mon application serait cassée si dans une future version d'iOS, le système d'interaction des documents ne place plus les fichiers dans Document/Inbox.

Donc mes questions sont:

  1. Recommanderiez-vous la solution A ou B?
  2. Utilisez-vous une approche différente et pourriez-vous peut-être donner un aperçu de la manière dont votre application gère Document/Inbox?
  3. Enfin, connaissez-vous un morceau de documentation officielle d'Apple qui couvre le sujet et que j'aurais négligé?

16voto

herzbube Points 3034

Depuis que j'ai posé cette question, j'ai mis en œuvre la solution suivante :

  • J'ai repensé mon application de sorte qu'elle traite immédiatement un fichier transmis via une interaction documentaire, sans impliquer l'utilisateur. Sauf en cas de plantage de l'application, ou de suspension et arrêt, en plein traitement du fichier, cela devrait toujours me laisser un Documents/Inbox propre.
  • Pour couvrir le cas (rare) d'un plantage ou d'une suspension/arrêt, mon application supprime le dossier Documents/Inbox lorsqu'elle est lancée normalement (c'est-à-dire sans interaction documentaire). Pour y parvenir, le chemin du dossier Documents/Inbox est nécessairement codé en dur.

Voici les réflexions qui ont guidé la solution :

  • Repenser l'application
    • Initialement, il semblait être une bonne idée de proposer à l'utilisateur le choix de la manière dont elle voulait qu'un fichier soit traité - après tout, offrir un choix rendrait l'application plus flexible et donnerait à l'utilisateur plus de liberté, n'est-ce pas ?
    • J'ai ensuite réalisé que j'essayais de déplacer la responsabilité de décider comment l'interaction documentaire devrait être gérée vers l'utilisateur. J'ai donc pris une décision difficile upfront, et suis allé joyeusement mettre en œuvre un système d'interaction documentaire simple et direct dans mon application.
    • Il s'avère qu'aucune interaction utilisateur signifie également que l'application est plus facile à utiliser, c'est donc une situation gagnant-gagnant, à la fois pour moi en tant que développeur et pour les utilisateurs de mon application.
  • Suppression du dossier Documents/Inbox lors du lancement de l'application
    • Supprimer le dossier Documents/Inbox lors du lancement de l'application n'est qu'une réflexion secondaire, pas une partie essentielle de la façon dont mon application gère l'interaction documentaire
    • Par conséquent, je suis tout à fait disposé à prendre le risque qu'Apple puisse modifier le chemin du système de fichiers du dossier de la boîte de réception à un moment donné à l'avenir. Le pire qui puisse arriver est que mon application commence à accumuler quelques fichiers laissés après des scénarios de plantage ou de suspension/arrêt.

Enfin, quelques réflexions pour le développement futur :

  • S'il s'avérait vraiment qu'il devrait y avoir plus d'une manière dont l'application peut gérer l'interaction documentaire, j'ajouterais une préférence utilisateur pour que l'utilisateur prenne une décision upfront, et que l'application n'ait pas besoin d'interrompre son traitement pour demander à l'utilisateur de faire un choix.
  • S'il s'avère absolument inévitable qu'une interaction utilisateur ait lieu en plein processus de gestion de l'interaction documentaire, j'examinerais cette approche : 1) Avant que l'utilisateur ne soit autorisé à interagir, déplacez le fichier de Documents/Inbox vers une sorte de dossier « de mise en attente » ; 2) Laissez l'interaction utilisateur se dérouler ; 3) Traiter le fichier dans le dossier « de mise en attente », de la manière que l'utilisateur a choisie. L'important ici est que le dossier de « mise en attente » se trouve à un emplacement connu et est entièrement géré par l'application. Si l'utilisateur suspend ensuite l'application et la tue en plein milieu de l'étape d'interaction utilisateur, une action appropriée peut être simplement entreprise lorsque l'application est lancée la prochaine fois.

MODIFIER

Dans iOS 7, il n'est plus possible de supprimer Documents/Inbox une fois qu'il a été créé. La méthode removeItemAtPath:error: de NSFileManager renvoie l'erreur Cocoa 513 qui se résout en NSFileWriteNoPermissionError (cf. cette liste de constantes Foundation). L'erreur ne semble pas liée aux autorisations POSIX, cependant, il semble plutôt que le système lui-même interfère avec la tentative de suppression (possiblement une protection de la structure du bundle de l'application ?).

Il est également intéressant de noter qu'aujourd'hui Apple mentionne explicitement Documents/Inbox dans la documentation de la méthode application:openURL:sourceApplication:annotation: de UIApplicationDelegate. Ils disent aussi que

[...] Votre application a la permission de lire et de supprimer des fichiers dans ce répertoire mais n'a pas la permission de les écrire. Si vous souhaitez modifier un fichier, vous devez d'abord le déplacer dans un répertoire différent.

Il y a d'autres informations sur le cryptage éventuel des fichiers dans la documentation, mais vous devriez vous renseigner vous-même à ce sujet.

7voto

fishinear Points 2452

Ce problème est devenu beaucoup plus compliqué avec l'introduction de l'application Fichiers et de la fonction "Ouvrir sur place".

Si vous n'avez pas activé l'option "Prise en charge de l'ouverture des documents sur place" dans votre info.plist, alors les choses restent sensiblement les mêmes, et les fichiers ouverts depuis une autre application apparaissent toujours dans le répertoire Documents/Inbox. Mais les fichiers ouverts depuis l'application Fichiers apparaissent dans une autre boîte de réception, actuellement à tmp/-inbox. Il est toujours recommandé de supprimer le fichier une fois que vous avez terminé avec lui, mais il est moins nécessaire de nettoyer occasionnellement le répertoire, car le répertoire tmp est nettoyé par iOS de temps en temps de toute façon.

Si vous avez activé l'option "Prise en charge de l'ouverture des documents sur place", alors les choses changent radicalement. Les fichiers ouverts depuis l'application Fichiers et certaines autres applications ne sont plus copiés dans une boîte de réception, mais ils vous sont transmis à leur emplacement d'origine. Il s'agit généralement d'un emplacement à l'intérieur de l'application Fichiers elle-même, à l'intérieur d'une autre application référencée depuis l'application Fichiers, ou même à un emplacement iCloud général. Si vous exposez les fichiers dans votre dossier Documents, alors cela pourrait même être l'un des fichiers de votre propre application.

Inutile de dire que si vous recevez un tel fichier, vous ne devez pas le supprimer. Mais si le fichier se trouve dans une boîte de réception, ce qui arrivera encore souvent, alors vous devez le supprimer. Pour déterminer cela, les options de l'appel application:openURL:options: contiennent une clé UIApplicationOpenURLOptionsOpenInPlaceKey. Si elle a pour valeur ( NSNumber) NON, alors le fichier est dans une boîte de réception et doit être supprimé. Si elle a pour valeur OUI, alors il est ouvert sur place et ne doit pas être supprimé.

Notez que pour les fichiers ouverts sur place, vous devez d'abord obtenir l'autorisation de les utiliser. Vous le faites en entourant l'accès au fichier par des appels startAccessingSecurityScopedResource et stopAccessingSecurityScopedResource. Consultez la documentation d'Apple pour plus de détails.

0voto

SMJ Points 11

Je suis actuellement confronté à ce même problème. Comme vous, je n'ai pas de bonne solution mais en réponse à vos questions, je penche plutôt vers l'option A que l'option B car je n'aime pas l'idée d'avoir potentiellement un problème avec les futures versions du système d'exploitation. Puisque, dans mon cas, il n'y a pas d'interaction utilisateur une fois que j'ai affiché l'aperçu du document, je peux le supprimer lorsque je reçois le rappel de délégué –documentInteractionControllerDidEndPreview:. Ceci est théorique dans la mesure où je n'ai pas encore codé cela et je n'y arriverai pas tout de suite car il s'agit d'un élément de faible priorité. Si cela ne fonctionne pas ou s'il y a d'autres problèmes, je reviendrai ici pour en faire part. La recherche Google que j'ai effectuée pour trouver de la documentation d'Apple m'a dirigé vers ce post StackOverflow. Je n'ai pas trouvé d'autres informations utiles d'Apple ou de quelqu'un d'autre sur le sujet.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X