Bindings "on the fly"

TiffTiff Membre
septembre 2004 modifié dans API AppKit #1
Dans la doc Apple sur les bindings, traduite par ProjectOmega, on trouve l'exemple des combattants, avec un menu pop-up et des accesseurs indexés.
http://www.projectomega.org/article.php?lg=fr&php=tuts_cocoaBindings&p=1
Tout fonctionne pour le tableau des combattants et le titre de la fenêtre.
Mais pb avec le pop-up :

Combattants[2315] An uncaught exception was raised
Combattants[2315] [<NSConstantString 0xf4024> valueForUndefinedKey:]: this class is not key value coding-compliant for the key selectedWeapon.
Combattants[2315] *** Uncaught exception: <NSUnknownKeyException> [<NSConstantString 0xf4024> valueForUndefinedKey:]: this class is not key value coding-compliant for the key selectedWeapon.
Combattants has exited due to signal 5 (SIGTRAP).

Déjà , une question toute bête : le menu doit être lié au contrôleur via arrayedObjects.
On trouve où arrayedObjects ? J'avais essayé arrangedObjects, puis tapé arrayedObjects à  la place. ça ne change rien.

Deuxième question : qu'est-ce qui ne va pas avec selectedWeapon ?
- (void)setSelectedWeapon:(NSMutableString *)aWeapon {
[aWeapon retain];
[selectedWeapon release];
selectedWeapon = aWeapon; }
- (NSMutableString *)selectedWeapon {
return selectedWeapon; }
:why?:
«1345

Réponses

  • ClicCoolClicCool Membre
    12:43 modifié #2
    Salut Tiff :)
    Le message d'erreur dit en effet que que ta classe Combattant n'est pas KeyValueCoding Compliante pour la propriété (variable d'instance) selectedWeapon.

    C'est donc qu'il ne trouve pas les accesseurs attendus.

    Ne serait-ce pas parceque le getter attendu selectedWeapon devrait renvoyer un objet de type Weapon et que de même le setter attendu devrait recevoir un objet de type Weapon, et non pas NSMutableString ?? 
    Dans la mesure ou selectedWeapon est défini comme Objet de type Weapon dans Combattant.h  ::)
  • TiffTiff Membre
    12:43 modifié #3
    dans 1094467274:

    Dans la mesure ou selectedWeapon est défini comme Objet de type Weapon dans Combattant.h  ::)

    Ben non, selectedWeapon est déclaré comme NSMutableString, tout comme weapon1, weapon2, weapon3. J'aurais du créer une classe spéciale ? Je reconnais que ce pourrait être intéressant pour une vraie appli, mais dans le cas présent, pourquoi serait-ce une source d'erreur ? ???
  • ClicCoolClicCool Membre
    12:43 modifié #4
    ah bon ? ???
    Dans ma version de ce tuto (du 24 février 2004) les armes sont des objets de type Weapons.
    Vérifie dans le nib quel type d'objet est spécifié par les infos du contrôlleur Weapons (Object Classe Name dans le panneau Attributes).

    Bizard ça ? une erreur de traduction peut-être ? ou une variante volontaire ? ???
  • TiffTiff Membre
    12:43 modifié #5
    dans 1094468682:

    ou une variante volontaire ?

    Je n'ai pas suivi de tuto, je me suis contenté de lire les commentaires de la doc, et ai essayé de faire une appli qui correspondait.
    J'avais laissé NSMutableDictionary dans Attributes. Je l'ai changé en NSMutableString, sans succès.

    Tu as un tuto spécial pour cet exemple ?
  • ClicCoolClicCool Membre
    12:43 modifié #6
    Oui j'a un tuto je sais plus d'où je l'ai sorti exactement mais j'essaierais de retrouver le lien (je suis sur un pc là ).
    Sinon, de toutes façons j'ai le code quelque part dans mon pb, il est à  disposition de qui le souhaite.
  • TiffTiff Membre
    12:43 modifié #7
    Je viens de tomber sur un projet Combatants ici :http://homepage.mac.com/mmalc/CocoaExamples/controllers.html
    où effectivement une classe Weapon est utilisée. Je vais voir.
  • ClicCoolClicCool Membre
    12:43 modifié #8
    Oui, à  première vue c'est bien ça que j'ai  ;)
  • TiffTiff Membre
    12:43 modifié #9
    Bon, en regardant rapidement le code, à  part le changement String - Weapon, je ne vois rien de différent. (Je suis d'ailleurs fier de mon premier "switch" dans l'accesseur indexé, on dirait qu'ils ont copié sur moi).
    Par contre, dans IB, il n'y a pas de contrôleur d'objet, le ArrayController Combatants ne semble pas lié à  l'AppController ?
    Sans doute va-t-il chercher les combattants pars accesseurs indexés aussi. J'étudie tout ça et je donne des nouvelles d'ici 48h. :P
  • muqaddarmuqaddar Administrateur
    12:43 modifié #10
    tiff a écrit :

    Combattants[2315] *** Uncaught exception: <NSUnknownKeyException> [<NSConstantString 0xf4024> valueForUndefinedKey:]: this class is not key value coding-compliant for the key selectedWeapon.
    Combattants has exited due to signal 5 (SIGTRAP).

    J'ai le même genre d'erreurs... le pb vient-il nécessairement du manque d'accesseurs ou ça peut venir d'une mauvaise connection dans IB ?
  • ClicCoolClicCool Membre
    12:43 modifié #11
    ça peut venir de I.B.
    en général c'est qu'il n'y a pas concordance entre le binding définit dans IB (ou dans le code!) et le code avec ses variables et leurs accesseurs. Au runTime le binding ne peut se mettre en place.

    Ceci dit les bindings ne sont pas toujours définis sous IB.
    En effet, j'ai (re)jetté un oeil sur le code des combatants dont je dispose (qui marche très bien)
    J'ai remarqué que le contrôleur des weapons est bindé sous I.B. (pour sont contenu) sur le contrôleur des combattants.
    MAIS sous IB le contrôleur des combattants est VIDE. Il n'y est pas défini de connexion ni de binding vers un contenu.
    C'est dans le awakeFromNib de l'AppContoller qu'est mis en place "à  la main" le binding définissant son contenu.
    [combatantsController bind: @&quot;content&quot; toObject: self<br />                                  withKeyPath:@&quot;combatants&quot; options:nil];
    

    Par ailleurs, d'autres bindings sont aussi faits main ...
    Ce serait pas par là  que ça se passe chez vous ?
  • TiffTiff Membre
    12:43 modifié #12
    Non, je ne crois pas. Les combattants marchent très bien.
    J'ai lié dans IB le Controleur Combattants à  AppController via un contrôleur d'objet ; mais je n'aime pas cette méthode, qui oblige à  ajouter un Controleur. Si on peut le faire avec une ligne de code, ce sera plus satisfaisant à  mon goût.
    Je laisse tomber pour l'instant, et je regarde les différents tuto de la page citée plus haut, pour me remettre dans le bain.
  • muqaddarmuqaddar Administrateur
    12:43 modifié #13
    J'essaie avec le wakeFromNib, il me dit MonControlleur "indeclared", ça se déclare comment aussi ça dans le .h ???

    Par ailleurs, mon appli est structurée comme ça :
    AppController -> GroupControlleur (NSArrayControlleur) -> SiteControleur(NSArrayControlleur)

    + le file'owner.

    - Est-ce que le file'owner doit déléguer AppController ?
    - Est-ce que GroupControlleur doti établir un connection outlet "content" avec AppControlleur ?

    merci
  • muqaddarmuqaddar Administrateur
    12:43 modifié #14
    dans 1094482056:

    Non, je ne crois pas. Les combattants marchent très bien.
    J'ai lié dans IB le Controleur Combattants à  AppController via un contrôleur d'objet ; mais je n'aime pas cette méthode, qui oblige à  ajouter un Controleur. Si on peut le faire avec une ligne de code, ce sera plus satisfaisant à  mon goût.
    Je laisse tomber pour l'instant, et je regarde les différents tuto de la page citée plus haut, pour me remettre dans le bain.


    C'ets marrant, ClicCool m'incitait justement à  me passer de controleurObjet la semaine dernière, mais je me perds alors dans les connections...
  • TiffTiff Membre
    12:43 modifié #15
    Il a deux mois, j'avais l'impression de maà®triser les connections. Maintenant je ne suis plus sûr de rien. Fait ch... les vacances ! Allez hop, au boulot !
  • muqaddarmuqaddar Administrateur
    12:43 modifié #16
    Bein en fait, je vois pas pkoi je ne peux binder le ContentArray de mon premier ArrayController sur mon AppControlleur mais uniquement sur le file'owner...
  • TiffTiff Membre
    12:43 modifié #17
    Pas uniquement sur le file's owner. Tu peux aussi sur un contrôleur d'objet.
    Ou alors directement sur ton AppControleur avec la ligne de code de Clicool.
    Mais je ne comprends pas pourquoi on ne peut pas le faire directement dans IB.
  • ClicCoolClicCool Membre
    12:43 modifié #18
    si si on peut moyener par I.B. mais ça manque d'élégance:
    /*
    This is not a document-based application.  There is currently no
    means of establishing a binding to an arbitrary object using
    Interface Builder.
    Bind the NSControllers to self using appropriate key paths.
    */

    Dixit le commentaire du code de l'AppController.
  • TiffTiff Membre
    12:43 modifié #19
    Tiens, voici une petite app qui ne sert à  rien, pouvez-vous tout de même me dire ce que vous en pensez ?

    [Fichier joint supprimé par l'administrateur]
  • ClicCoolClicCool Membre
    12:43 modifié #20
    Voila un parfair squelette de la façon d'éviter un contrôler objet fantoche qui ne sert qu'à  établir le binding directement dans I.B. :D

    On se demande pourquoi il n'est pas possible dans I.B. de définir un binding direct comme tu l'as défini et qui ne prend finalement qu'une ligne de code dans ton awakeFromNib.  :(
  • TiffTiff Membre
    12:43 modifié #21
    Aurais-tu une idée pour récupérer le jour sélectionné pour le mettre, par exemple, en titre de la fenêtre ? o:)
    J'ai bien essayé de lier la fenêtre au contrôleur par title Bind to popUpController with key selection dans IB, mais messages d'erreur.
    Bien sûr sans créer de classe Jour, avec une propriété nomDuJour.
  • ClicCoolClicCool Membre
    12:43 modifié #22
    Ben comme ça à  froid, le plus simple est de créer une variable d'instance dans ton AppController:
    NSString * leJour;
    

    Qui sera chargée de conserver la sélection actuelle du popup
    Puis de binder la propriété "selectedObject" de ton pop up sur cette chaine.
    Soit programmatiquement (le plus propre)
    Soit en créant un NSObjectController intermédiare ....

    Puis tu bindes la propriété titre de ta fenêtre sur leJour.  ;)
  • TiffTiff Membre
    12:43 modifié #23
    Oui, j'ai déjà  pensé à  mettre un objectController et lier le menu à  ce controleur via selectedObject, mais du coup plus rien dans le menu. Bon, je n'avais pas codé NSString *leJour; mais je ne pense pas que ça change quoi que ce soit. J'essaye quand même. Merci.
  • TiffTiff Membre
    12:43 modifié #24
    Ah si, finalement le menu s'affiche normalement, mais avec No Value sélectionné. Bon, je vais voir ce que je peux faire dans -init.
  • ClicCoolClicCool Membre
    12:43 modifié #25
    Soit un outlet popUp pointé sur ton popUp et un outlet maWindow sur ta fenêtre.
    Tu n'as plus qu'à  ajouter ces 2 lignes dans ton awakeFromNib:  8)
    <br />     [popUp bind: @&quot;selectedObject&quot; toObject: self withKeyPath: @&quot;leJour&quot; options: nil]; <br />  [maWindow bind: @&quot;title&quot; toObject: self withKeyPath: @&quot;leJour&quot; options: nil];
    
  • TiffTiff Membre
    12:43 modifié #26
    Eh eh, c'était exactement ce que j'étais en train de faire. Bon d'accord, avec cinq minutes de retard. Mais ça marche au poil.
  • TiffTiff Membre
    12:43 modifié #27
    Si ça intéresse quelqu'un :

    [Fichier joint supprimé par l'administrateur]
  • ClicCoolClicCool Membre
    12:43 modifié #28
    Ben oui, les bindings "on The Fly" sont très efficaces, quoiqu'un poil délicats à  débugger.
    C'était au programme des volets à  venir de mon tuto. mais là  j'ai pas assez de temps pour l'écrire et il commence à  y avoir pas mal d'exemples sur le net ...
  • TiffTiff Membre
    12:43 modifié #29
    dans 1094504363:

    j'ai pas assez de temps pour l'écrire

    :'(
  • ClicCoolClicCool Membre
    12:43 modifié #30
    En attendant essaies donc de virer l'initialisation de leJour et de mettre un place holder dans tes bindings pour cette occasion.
    Un bon exrecice  ;D
  • TiffTiff Membre
    12:43 modifié #31
    Juste au moment où j'allais me coucher. Sadique !
Connectez-vous ou Inscrivez-vous pour répondre.