Quel est le meilleur moyen pour mettre à  jour un Plist

al33eral33er Membre
15:01 modifié dans API UIKit #1
BOnjour,

Je cherche le meilleur (le plus facile) moyen pour mettre à  jour un fichier .plist.

root -> array
  item 1 -> dictionnary
      lettre -> string
      pays  -> array
        item A -> dictionnary
            nomPays -> string
            Fruits -> array
                item 1 -> dictionnary
                      nomFruit -> string
                      couleur -> string

j'ai deux fenêtres pour présenter les deux derniers arrays (le premier permet de faire les sections) et un troisième pour créer des nouveaux fruits.

Dans la troisième fenêtre, par l'ajout dans la liste je voudrais aussi mettre à  jour le fichier .plist à  jour.

Y-a-t-il un moyen simplement ou faut-il rechercher endroit ou on se trouve, insérer le fruit (un item) dans le NSArray et ensuite mettre à  jour le fichier ou le recréer (je ne sais pas).

Merci d'avance pour votre aide.

Alexandre.

Réponses

  • Philippe49Philippe49 Membre
    15:01 modifié #2
    Personnellement, je ne connais pas de moyen de changer partiellement un fichier sous Unix.
    On le réécrit. Il y a souvent des classes/méthodes de persistence, qui font le travail à  ta place, mais cela revient à  écraser le fichier en réécrivant dessus.
  • AliGatorAliGator Membre, Modérateur
    15:01 modifié #3
    Déjà , un fichier plist ne se met pas vraiment à  jour, la pratique fait qu'en réalité on charge notre plist dans un NSArray (ou autre selon le type racine du plist), on modifie le NSArray, et quand on veut "sauver" on réécrit tout le NSArray dans le plist ([tt]writeToFile:atomically:[/tt] de mémoire). En fait tu n'as pas à  savoir vraiment comment est foutu ton plist (certains sont au format ASCII, d'autres au format XML, d'autres au format binaire...), tu ne manipules que ton NSArray, que tu charges depuis ton plist ou sauves dans ton plist.

    Après, pour manipuler ton NSArray, oui il faut que tu mémorises quand tu affiches ta vue (via [tt]presentModalView:animated:[/tt] j'imagine ?) à  quel endroit tu étais dans ton NSArray.
    Par exemple quand tu crées ton ViewController associé, tu mémorises dedans où tu es rendu dans tes listes (où tu vas ajouter ton fruit). Et quand tu cliques sur le bouton pour valider, tu insères ton fruit dans le tableau à  la bonne place.
    Ou alors dans e ViewController principal (et pas celui de ta vue pour ajouter un fruit) tu gardes la position courante (tu dois bien l'avoir déjà  qqpart de toute façon j'imagine) et tu écoutes la méthode qui te prévient quand ta modalView est dismissée (j'ai pas vérifié mais il doit sûrement y avoir une delegate method) ou alors tu recrées le mécanisme de delegate ou de target/action, et tu appelles alors une méthode de ton choix quand tu valides la création de ton fruit, méthode qui pourra être une méthode de ton ViewController principal (qui lui connaà®t le "fruit" courant) et qui va ajouter le fruit dans le tableau au bon endroit...
  • Philippe49Philippe49 Membre
    15:01 modifié #4
    Quand à  la création et l'insertion dans ton arborescence connais-tu la classe NSIndexPath ?

    Il me semble que lors de ton Drill Down (navigation dans l'aborescence) dans tes vues tu dois pouvoir transmettre (ou mettre à  jour dans une instance connue de tous les views controllers) un index path précisant l'endroit où tu agis.  
  • al33eral33er Membre
    15:01 modifié #5
    Merci à  vous deux. Je regarde cela et je vous tiens au courant.

    Alexandre.
  • al33eral33er Membre
    février 2009 modifié #6
    Super, j'avance, mais il me manque une dernière chose.

    Mon fichier plist, je peux le lire super facilement, mais lorsque je veux le réécrire par la méthode writetofile. Il me fait un code retour NO.

    NSString * path=[[NSBundle mainBundle] pathForResource:@AFruit ofType:@plist];
    NSMutableArray * listFruits=[[NSMutableArray alloc] initWithContentsOfFile:path];
    NSLog([listFruits description]);
    BOOL ecrit = [listFruits writeToFile:path atomically:YES];
    ecrit = NO en retour et pourtant je ne fais rien.

    Est-ce que le fichier doit être écrit d'une façon spécifique ?

    voici mon fichier en version texte :

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">;
    <plist version="1.0">
    <array>
    <dict>
    <key>Initial</key>
    <string>F</string>
    <key>States</key>
    <array>
    <dict>
    <key>State</key>
    <string>France</string>
    <key>Fruits</key>
    <array>
    <dict>
    <key>name</key>
    <string>Orange</string>
    <key>Couleur</key>
    <string>Orange</string>
    </dict>
    </array>
    </dict>
    </array>
    </dict>
    </array>
    </plist>


    Alexandre.
  • MalaMala Membre, Modérateur
    15:01 modifié #7
    C'est normal. Sur l'iPhone/iPod, le répertoire des ressources n'est accessible qu'en lecture.  ;)
  • AliGatorAliGator Membre, Modérateur
    15:01 modifié #8
    Oui du coup le plus simple c'est :
    1) Avoir un plist dans les ressources qui te sert de valeurs par défaut
    2) Utiliser NSUserDefaults pour stocker ton dernier tableau s'il a été modifié

    A l'ouverture de ton appli, tu lis les NSUserDefaults. Si ton tableau n'est pas dedans, tu le lis à  partir du Plist, sinon tu le lis à  partir des UserDefaults. Et quand tu veux sauver ton tableau modifier, tu le sauves dans les NSUserDefaults puisque tu ne peux pas écraser le plist dans les ressources.

    Une autre solution est d'écrire le plist dans le répertoire accessible en écriture sur l'iPhone (chaque application a un espace dans lequel elle est la seule à  avoir le droit de lire/écrire, c'est un peu l'équivalent de son "Application Support" sur Mac) mais pour ton cas je vois pas l'intérêt, les NSUserDefaults sont bien plus simples à  manipuler et plus adéquats.
  • al33eral33er Membre
    15:01 modifié #9
    Merci Ali et Maya,

    Effectivement j'utilise beaucoup le NSUserdefaults, alors je continue.
    Petit à  petit l'oiseau fait son nid.

    J'ai un souci quand même. Comment un mutableArray peut devenir non mutable ?

    Alexandre.
  • MalaMala Membre, Modérateur
    15:01 modifié #10
    dans 1235844341:

    Merci Ali et Maya,

    Maya c'est une abeille non?  :)

    dans 1235844341:

    J'ai un souci quand même. Comment un mutableArray peut devenir non mutable ?

    Tu dois le transformer en faisant une copie de ton objet mutable.

    <br />NSArray *monArrayNonMutable = [[monArrayMutable copy] autorelease];<br />
    


    Tu noteras au passage que j'ai ajouté un autorelease après la copy. Par convention en Objective-C, init/new/copy/mutableCopy ne renvoient jamais d'objet autorelease. Il faut donc le savoir et y faire attention sous peine d'avoir des fuites mémoire.



  • al33eral33er Membre
    15:01 modifié #11
    Bon, j'avance encore un peu. Dans ma plist, j'ai pu mettre les fonctionnalités ajouter et supprimer pour le niveau fruit.
    J'ai aussi pu ajouter au niveau plus haut, le niveau pays la fonctionnalité ajout.
    Par contre lorsque je veux supprimer, impossible. Il me dit à  l'execution que j'essaye d'appliquer une opération remove (mutable) sur un ojbet qui ne l'ai pas. L'array est bien déclaré mutable et les dictionnaire et array de niveau inférieure aussi.

    Je ne comprend pas.
    Merci pour votre aide s'il vous plaà®t.
    Alexandre.
  • MalaMala Membre, Modérateur
    15:01 modifié #12
    dans 1236121734:

    Bon, j'avance encore un peu. Dans ma plist, j'ai pu mettre les fonctionnalités ajouter et supprimer pour le niveau fruit.
    J'ai aussi pu ajouter au niveau plus haut, le niveau pays la fonctionnalité ajout.
    Par contre lorsque je veux supprimer, impossible. Il me dit à  l'execution que j'essaye d'appliquer une opération remove (mutable) sur un ojbet qui ne l'ai pas. L'array est bien déclaré mutable et les dictionnaire et array de niveau inférieure aussi.

    Je ne comprend pas.
    Merci pour votre aide s'il vous plaà®t.
    Alexandre.

    Déclarés mais sont-ils initialisé en mutable? Je pense que non. Si tu fais des copies il faut aussi quelles soient mutables (mutableCopy à  la place de copy).
  • al33eral33er Membre
    15:01 modifié #13
    Je pense qu'elle le sont. En fait a chaque fois que je les initialise je me fait par NSMutable Array arraywitharray et les dictionnaires avec des NSMutableDictionnary dictionnarywithDictionnary.

    Une petite précision. Je stocke les infos dans les defauts pour pouvoir les réafficher en l'état sur une prochaine exécution.

    Lors que je ré-execute et que je supprime une ligne pays cela fonctionne parfaitement. Là  ou cela ne fonctionne pas c'est je viens juste de rajouter la ligne pays dans le contrôleur inférieur.

    Alexandre.
  • MalaMala Membre, Modérateur
    15:01 modifié #14
    dans 1236123229:

    Je pense qu'elle le sont.

    Ton programme se range de mon côté pour dire que non...  :)

    Plus sérieusement, il faut que tu regardes où et comment tu initialises ton tableau en passant au debug en pas à  pas. Il y a forcément quelque chose qui cloche.
  • al33eral33er Membre
    15:01 modifié #15
    Y a t-il une façon pour voir si un array est mutable ou pas dans le debugger ?
  • BaardeBaarde Membre
    15:01 modifié #16
    dans 1236124058:

    Y a t-il une façon pour voir si un array est mutable ou pas dans la console de debuggage ?

    Oui, en écrivant ceci dans le debugger :
    print (char *) class_getName((Class) [myArray classForArchiver])
    
  • al33eral33er Membre
    15:01 modifié #17
    Merci beaucoup. ça y est je m'en suis sorti.

    Je vais passer à  l'optimisation maintenant.

    Alexandre.
Connectez-vous ou Inscrivez-vous pour répondre.