NSFileManager -> createDirectoryAtPath:withIntermediateDirectories:attributes:er

pauline3869pauline3869 Membre
04:46 modifié dans API UIKit #1
Bonjour a tous,

Je suis nouvelle sur ce forum. Cela fait un moment que je suis dans l'impasse avec le morceau de code que je vais décrire ci-dessous. J'ai eut beau chercher je n'ai rien trouvé qui puisse expliquer le pourquoi du comment vis a vis de l'erreur suivante :

En gros mon but est de créer tout simplement un dossier dans le dossier de mon application iPad. Pour cela, je récupère le path du dossier documents de mon application comme ceci :

NSArray *directories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);<br />	NSString *path= [directories count] ? [directories objectAtIndex:0] : nil;<br />	NSString *finalPath = [NSString stringWithFormat:@&quot;%@/MonDossier/&quot;, path];


Ensuite j'essaie tout simplement de créer le dossier comme ceci :

if ([[[NSFileManager alloc] init] fileExistsAtPath:getDocumentPath()] == NO) {<br />		NSLog(@&quot;%s&quot;, [[[NSFileManager alloc] init] fileSystemRepresentationWithPath:finalPath]);<br />		NSLog(@&quot;ici : %@&quot;, finalPath);<br />		BOOL test = [[[NSFileManager alloc] init] createDirectoryAtPath:finalPath withIntermediateDirectories:YES attributes:nil error:nil];<br />&nbsp; &nbsp; &nbsp; &nbsp; if (test == YES)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NSLog(@&quot;success&quot;);<br />&nbsp; &nbsp; &nbsp; &nbsp; else<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NSLog(@&quot;fail&quot;);<br />	}<br />	if ([[[NSFileManager alloc] init] fileExistsAtPath:finalPath] == NO)<br />		NSLog(@&quot;le fichier n existe tjs pas&quot;);<br />	else {<br />		NSLog(@&quot;le fichier a ete cree&quot;);<br />	}


Et voila le retour que j ai :
# success
#le fichier a ete cree


Seulement lorsque je vais verifier dans le dossier indiqué par le path généré "finalPath", aucun dossier "MonDossier" n'y a été créé. Le plus étrange dans l'histoire c'est que jusqu'à  il y a quelques jours, cela fonctionnait et je pouvait retrouver ce dossier. 

Si quelqu'un aurait une idée sur ce qui peut clocher je prend volontiers et vous remercie d'avance...

Pauline.

Réponses

  • AliGatorAliGator Membre, Modérateur
    04:46 modifié #2
    Bonjour Pauline et bienvenue.

    Si tu passes une NSError à  la méthode [tt]createDirectoryAtPath: withIntermediateDirectories: attributes: error:[/tt], que contient la NSError (si elle n'est pas nil au retour de l'appel de la méthode) ?
    NSError* err;<br /><br />BOOL test = [[[NSFileManager alloc] init] createDirectoryAtPath:finalPath withIntermediateDirectories:YES attributes:nil error:&amp;err];<br />NSLog(@&quot;error : %@&quot;,err);
    


    PS : Sinon côté gestion mémoire il y aurait pas mal de choses à  revoir dans ton code. Tu fais des "alloc+init" un peu partout (surtout sur NSFileManager) mais aucun release, tu as donc des fuites mémoire dans ton code.
  • pauline3869pauline3869 Membre
    04:46 modifié #3
    Bonjour,

    pour commencer merci pour l'aide :) .
    Pour ce qui est de l'error elle est égale a nil...

    Pour les release j'avoue que c'est un peu crade mais vu que c'était juste un test j'ai pas pris le temps de faire ca proprement (honte sur moi ...).
    Pour le reste, jviens de tester de faire une nouvelle appli bidon avec ces lignes de code dans le viewDidLoad ... Et la ca marche ! c est a s'arracher les cheveux !!! je comprend pas pourquoi ca ne fonctionne plus dans mon appli ...

  • AliGatorAliGator Membre, Modérateur
    04:46 modifié #4
    Je pense que c'est dû au simulateur : tu es sûr d'avoir vérifié au bon endroit, en suivant le bon chemin ?
    En effet parfois quand tu relances ton application dans le simulateur après des modifications et recompilation, il utilise un nouveau UUID pour ton application. Donc comme les applications installées dans le simulateur sont dans un dossier du genre "/jesaisplusoù/iPhone Simulator/4.2/ABCD-1234-BLABLA/", il suffit que l'identifiant "ABCD-1234-BLABLA" change parce que tu as fait une nouvelle compilation et que ça lui arrive parfois de générer comme si c'était une nouvelle appli.
    Du coup si tu étais habituée à  regarder dans un dossier donné et que le dossier a changé (vu que les UUID/identifiants générés sont pas très user-friendly, tu as pu ne pas réaliser qu'il avait changé ou regarder dans un dossier au nom très similaire), il se peut très bien que le dossier soit bien créé comme attendu et comme le laissait comprendre ton code... mais que tu ne regardais pas au bon endroit dans le Finder pour vérifier de ton côté !

    Si tu es passé à  Xcode4 depuis, ou a changé de SDK (4.3, ...) et donc que ça s'est mis dans un autre dossier du simulateur, etc... ça peux expliquer. Si tu as toujours ton ancien projet, vérifier à  2 fois le chemin du dossier dans lequel tu regardais :P
  • pauline3869pauline3869 Membre
    04:46 modifié #5
    Malheureusement oui... :(

    je vérifie a chaque fois en vérifiant ce que me retourne la ligne :

    NSLog(@&quot;ici : %@&quot;, finalPath);
    


    Je vais a chaque fois dans le dossier correspondant ... :'(


  • LeChatNoirLeChatNoir Membre, Modérateur
    04:46 modifié #6
    :o Et les gars, y ' a une fille  <3 <3 <3 <3 <3 <br />
    Bienvenue Pauline, bon d'habitude, c'est moi qui ait des problèmes et les autres qui me les résolvent  8--)

    Mais comme t'es une fille, et que force est de constater que ça déstabilise complètement Ali, ben je me fend d'une réponse...  :P

    Je serai toi, je dégagerai complètement le dossier actuel du simulateur. Genre "/jesaisplusoù/iPhone Simulator/4.2/ABCD-1234-BLABLA/" que ton finalPath doit t'indiquer, ben tu shootes tout et tu rebuild et relance.

    Voilà . C'est pas très fin, très empirique mais ça devrait le faire...

    Non ?
  • pauline3869pauline3869 Membre
    04:46 modifié #7
    Bonjour LeChatNoir,

    j'ai essayé ce que tu propose mais rien n'y a fait...
    En revanche maintenant mon code fonctionne mais je ne comprend tjs pas pourquoi maintenant ca marche  ???

    En gros le truc de mon appli c est de télécharger directement des fichiers en direct live sur un compte google docs... Or tout a commencé a foirer le jour ou j'ai fait de grosses modifs sur le compte gdocs...

    Du coup au bénéfice du doute j ai décidé de recréer un compte googledocs, et avec le nouveau compte ca fonctionne ... sauf que je ne comprend absolument pas pourquoi (en quoi la création d un dossier en local et la connexion au compte google docs est elle reliée ??? ) .... Bref j'ai intérêt de trouver parce que du coup c'est pas le summum de la stabilité lol ...

    Merci pour l'aide en tout cas... Maintenant il faut que je trouve ou est enfouie mon erreur de blonde ;) .
  • laudemalaudema Membre
    04:46 modifié #8
    Essaye plutôt avec [NSFileManager defaultManager]
    Et tu sauras le pourquoi de ma signature ;/
  • laudemalaudema Membre
    04:46 modifié #9
    Désolé, clic sur mauvais lien, fatigue .... >:)
  • pauline3869pauline3869 Membre
    04:46 modifié #10
    Bon j'ai trouvé mon erreur (au passage merci laudema pour la réponse).
    C'était effectivement une erreur de blonde  <3 , c'est un peu honteux pour moi mais comme vous m'avez aidé vous gagnez le droit de rigoler un peu ...<br />En gros a un moment donné je fait un check pour supprimer les documents n'existant plus sur le googleDocs afin de les supprimer aussi sur l'appli. Or dans ma methode qui se charge de cela, j'ai fait deux erreurs :
    => la premiere c est que j'utilisais "isequaltostring" pour comparer les noms de dossiers ... Or lorsqu'il y a des accents dans le titre, "isequaltostring" retourne FAUX meme si les deux chaines sont les memes ... Il fallait donc utiliser "compare".
    => la seconde et non la moindre, c'est que comme une grosse nouille lorsque je supprime un dossier qui n'existe plus, j'ai laissé un miserable "stringByDeletingLastPathComponent"....

    Du coup explication, j ai des dossiers avec des accents. Au lancement de l'appli ces derniers ne matchaient pas puisque j'utilisais "isEqualToString" du coup comme je supprimait les dossiers qui ne matchaient pas en faisant de sucroit " suppression de DossierContenant/ " au lieu de "DossierContenant/dossierAvecAccent-éééé/" beh jsupprimait tous mes dossiers

    Bref c'est la honte .... jvais me cacher ...  :o  
  • laudemalaudema Membre
    04:46 modifié #11
    Faut pas !
    Si ça peut te  consoler je partage ta honte car j'ai dit une bêtise en mentionnant defaultManager, - init est préférable à  + defaultManager car elle est thread safe.
    Donc j'ai tout faux et le rouge de la honte m'envahit à  mon tour  :o

    Pour me faire pardonner, sans savoir ce que tu as utilisé pour comparer les chaà®nes cette fois, tu as deux méthodes (peu connues) qui peuvent t'intéresser dans ce genre de manipulations

    stringByFoldingWithOptions: Qui te permet de "replier" la chaine de caractères en utilisant les opérateurs de comparaison par exemple (NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch) donné comme argument à  [tt]Options:[/tt] te supprimera les caractères diacritiques et les accents. Si tu l'appliques à  tes chaines tu peux ensuite les comparer via isEqualToString,

    completePathIntoString:caseInsensitive:matchesIntoArray:filterTypes que j'ai été très content de découvrir:
    On déclare une chaà®ne *aCompleter qu'on passera par référence, pareil pour un tableau *aRemplir qu'on déclare seulement, on crée un tableau *aGarder avec les extensions qu'on veut récupérer et un BOOL caseSensitive puis on applique à  un début de chemin:
    retour = [@&quot;/DisqueDur/LeChemin/DuDossierDe/mesfichiersQuiCommencentParA&quot; completePathIntoString:&amp;aCompleter caseSensitive:caseSensitive matchesIntoArray:&amp;aRemplir filterTypes:aGarder]
    

    En retour de la méthode le nombre de fichiers trouvés,  dans aCompleter la plus longue des chaines qui a pu être complétée et dans aRemplir toutes les chaines qui ont correspondu.

    Tu n'en auras peut être pas besoin mais comme on ne sait pas spontanément qu'elles existent on peut écrire un code assez fastidieux pour arriver au même résultat !

    Enfin une instance de NSFileManager qui fonctionne pas quand elle devrait, chez moi c'est souvent parce qu'elle est 0x0. Mais tu verras ça plutôt l'étape d'après: quand tu relacheras tout ce que tu as créé/copié/retenu parce que sinon ton usage de la mémoire devient critique (et sur les iphones ça peut aller vite).
  • pauline3869pauline3869 Membre
    04:46 modifié #12
    Merci beaucoup pour cet ajout très enrichissant. Je connaissait dejà  un peu stringByFoldingWithOptions mais je n'ai pas voulu l'utilisé par peur de ceci (après il est possible que je me trompe) :

    - si je compare deux NSString en supprimant les accents et la casse, cela veux dire que "uneChaineDeTest_é" et "unechainedetest_e" matchent ? Or dans ce cas la il faut (pour mon cas) que mes deux fichiers soit bel et bien reconnus comme deux fichiers differents....

    En revanche je ne connaissait absolument pas completePathIntoString:caseInsensitive:matchesIntoArray:filterTypes et jpense que si je l'avait connu plus tot cela m'aurait effectivement évité bien des galères .... Du coup je note pour la prochaine fois :) , c'est très bon a savoir !

    Encore Merci !
  • AliGatorAliGator Membre, Modérateur
    04:46 modifié #13
    En fait une petite addition pour le "folding" :
    • En effet on peut utiliser le "folding" pour supprimer toutes les subtilités d'une chaà®ne qui risqueraient de faire foirer une comparaison. Par exemple on peut utiliser le folding pour supprimer les diacritiques (accents, cédilles, ...) d'une NSString et qu'ainsi "toto_é" et "toto_e" soient considérés comme identiques. Mais ça, c'est pas ce que tu veux.
    • Par contre ce qui t'arrive certainement c'est que dans tes 2 chaà®nes que tu compares, la forme des diacritiques n'est pas la même. En effet, en unicode, les caractères accentués peuvent être représentés de plusieurs façons, leur forme précomposée ou décomposée. Par exemple pour la lettre "é" :
      • Soit on le représente directement avec le caractère "é", ce qu'on peut faire parce que ce caractère existe dans la table Unicode (ce qui n'est pas forcément le cas de toutes les lettres accentuées, genre le "o" barré et avec un ° au dessus est trop rarement utilisé et dans trop peu de langues pour exister directement tel quel en unicode)
      • Soit, parce que le caractère n'existe pas "tout fait" dans la liste des caractères unicode, soit parce qu'on a envie de pas faire comme tout le monde, on peut représenter "é" comme étant "un e avec un accent aigu", ce qui se représent en unicode par 2 "codes", le code de l'accent aigu et le code de la lettre "e". Et quand le système va voir l'association des 2 codes, il va représenter cela à  l'écran par sa forme recomposée "é". Cette forme décomposée (l'accent et la lettre séparés) permet de représenter des lettres à  diacritiques peu courantes et n'existant pas forcément toutes-faites dans la police de caractères utilisée.



    A cause de cette subtilité, une chaà®ne contenant un "é" précomposé (directement le caractère "é") et une autre contenant le caractère décomposé en "accent + e" risquent d'être considérées comme différentes.
    Grace au "folding", on peut faire en sorte que les deux chaà®nes soient représentés utilisant le même standard (représentation des caractères à  diacritiques tout en "décomposé" -- ou en "précomposé", au choix, mais tout pareil en tout cas) et donc que la comparaison de 2 chaà®nes avec isEqualToString fonctionne correctement.

    Quand vient la présence d'accents dans les chaà®nes, il y a souvent pas mal de subtilités de ce genre dont il faut un peu avoir conscience pour éviter les pièges. Y'a pas à  rougir, on est tous déjà  tombés dedans :P
  • LeChatNoirLeChatNoir Membre, Modérateur
    04:46 modifié #14

    Laissez là  rougir bon sang  :D  ;D

  • pauline3869pauline3869 Membre
    04:46 modifié #15
    Tout s'explique :)

    J'imaginais bien que ca serait à  cause d'un truc de ce genre la .... Pour débugger j'avais tester d'afficher mes deux string en UTF8 et ça ne sortait effectivement pas la même chose.
Connectez-vous ou Inscrivez-vous pour répondre.