[Bindings]VLCKit, révélateur de mon incompréhension coriace aux Bindings

OmfraaxOmfraax Membre
septembre 2008 modifié dans API AppKit #1
Bonjour à  tous,

Je me suis mis aux Bindings il ya quelques semaines déjà  et il me semble que je comprends (ou du moins j'arrive à  les faire marcher) de plus en plus mais j'arrive à  un nouveau point de blocage.

Depuis que VLC a sorti le VLCKit, je m'en sert de prétexte pour me faire un peu la main et voilà  le problème.

Il y a une classe VLCMediaPlayer qui possède une variable de type VLCTime et deux beaux accessors :
<br />- (void)setTime:(VLCTime *)value;<br />-(VLCTime *)time;<br />


Ensuite, dans le fichier VLCTime.h, on trouve la property suivante
<br />@property (readonly) NSString * stringValue;<br />


Voilà  pour le VLCKit...

Ensuite, j'ai fabriqué une classe Root qui contient essentiellement ça (avec bien sûr des méthodes du genre play et un Outlet sur une View pour afficher la vidéo mais là  n'est pas le problème)
<br />@interface Root : NSObject {<br />	<br />	VLCMediaPlayer* myPlayer;<br />}<br />


Dans l'interface, j'ai un NSTextField dont je veux qu'il affiche ce fameux time, si possible avec des Bindings pour la beauté du geste.

Pour commencer j'y vais cool, je remarque déjà  que VLCMediaPlayer envoie à  son delegate un message
<br />- (void)mediaPlayerTimeChanged:(NSNotification *)aNotification;<br />

Donc j'appelle à  l'initialisation un petit
<br />[myPlayer setDelegate:self];<br />

pour être notifié.
Je modifie ma classe root pour y rajouter une nouvelle property
<br />@interface Root {<br />....<br />NSMutableString *timeValue;<br />}<br />...<br />@property(retain) NSString *timeValue;<br />...<br />@end<br />


Et enfin, j'implémente mediaPlayerTimeChanged :
<br />- (void)mediaPlayerTimeChanged:(NSNotification *)aNotification {<br />&nbsp; &nbsp;[self setValue:[[myPlayer time] stringValue] forKey:@&quot;timeValue&quot;]<br />}<br />


et enfin je binde le NSTextField de mon interface avec la key timeValue, via un ObjectController de IB.

Et là , tout marche bien !!

Mais je me dis que c'est bête d'avoir créé une variable timeValue quand on fait des bindings surtout que les classes VLCMediaPlayer et VLCTime m'ont l'air d'être KVC-compliantes.

Je teste en faisant provisoirement de mon objet Root un Observer pour la clé time que la mise à  jour de cette variable renvoie bien des notifications KVO--> tout est OK.

Puis je basarde ma variable timeValue, l'implémentation de  la méthode mediaTimeChanged et je fais de ma variable myPlayer une property :
<br />@property(readonly) VLCMediaPlayer * myPlayer; <br />


Enfin je binde directement mon NSTextField à  la key myPlayer.time.stringValue.

Et là  patatras, il ya le Null placeHolder dans mon NSTextField au lieu de l'affichage escompté...

Qu'est ce qui ne va pas ?
Si aussi vous voyez des maladresses (par exemple, je suis pas très l'aise sur la necessité de déclarer les variables comme @property pour pouvoir les binder ...), n'hésitez pas !

Merci d'avance pour votre aide.

Réponses

  • Philippe49Philippe49 Membre
    septembre 2008 modifié #2
    dans 1222025840:

    <br />@property(readonly) VLCMediaPlayer * myPlayer; <br />
    


    Ce readonly ne poserait-il pas problème ? Certes ce n'est pas directement myPlayer qui est en binding, mais c'est quand même très lié.
    Comment le binding réagit dans ce cas ? Il faudrait essayer sur un exemple simple. 



    dans 1222025840:

    Et là  patatras, il ya le Null placeHolder dans mon NSTextField au lieu de l'affichage escompté avec les bindings ...

    Vérifier si les initialisations suivent une bonne chronologie .

    dans 1222025840:

    Par exemple, je suis pas très l'aise sur la necessité de déclarer les variables comme @property pour pouvoir les binder ...

    Rien n'oblige les @property pour le binding, ceci dit, pour faire le setter et le getter proprement à  la main qui agissent correctement ... 

  • OmfraaxOmfraax Membre
    septembre 2008 modifié #3
    Bon, j'ai viré tout ce qui était @property, ça ne marche toujours pas (par contre un autre binding simple qui marchait avant marche toujours  ) ...

    Rien n'oblige les @property pour le binding, ceci dit, pour faire le setter et le getter proprement à  la main qui agissent correctement ... 

    En fait, je m'interrogeais globalement sur  l'utilité des getter/setter  (à  la main ou à  la sauce @property) puisque ça a l'air de très bien marcher sans...

    Revenons à  nos moutons :
    Il ya peut-être effectivement un problème dans les initialisations sachant que myPlayer est créé dans le awakeFromNib. Je l'ai initialisé à  ce niveau car il faut une NSView (qui est en IBOutlet) pour l'initialiser et il me semble me souvenir que pour être sûr d'avoir des bons Outlet, il faut attendre d'être dans -awakeFromNib

    Après, honte à  moi, mais j'avoue que je ne suis pas non plus hyper au taquet entre ce qu'il faut mettre dans le -init et ce qu'il faut mettre dans le -awakeFromNib.

    Merci déjà  pour cette première réponse !
  • Philippe49Philippe49 Membre
    septembre 2008 modifié #4
    dans 1222034085:

    En fait, je m'interrogeais globalement sur  l'utilité des getter/setter  (à  la main ou à  la sauce @property) puisque ça a l'air de très bien marcher sans...

    Mon expérience personnelle, c'est qu'un setter ou un getter qui ne fait que renvoyer la valeur ou donner la valeur est inutile si on utilise valueForKey et setValue:forKey: ou les bindings. Ces méthodes peuvent par contre être utiles pour intercepter une mise à  jour ou une demande de valeur en vue d'une action spéciale.

    [EDIT] ceci dit la doc est ambigue
    Donc, avec les property, on a plus de sécurité sur le bon fonctionnement.

    dans 1222034085:

    Revenons à  nos moutons :
    Il ya peut-être effectivement un problème dans les initialisations sachant que myPlayer

    Il y a un moyen simple de le savoir : dans awakeFromNib mettre à  jour la valeur bindée sur le modèle
       [[myPlayer time] setValue:@truc forKey:@timeValue]
    Si cela se reporte sur le TextField, le binding devrait être au point et il y a de fortes chances que le problème soit dans l'ordre des initialisations.



  • Philippe49Philippe49 Membre
    13:47 modifié #5
    dans 1222034085:

    Il ya peut-être effectivement un problème dans les initialisations sachant que myPlayer est créé dans le awakeFromNib.

    Oui cela pose problème.
    Si tu veux laisser là  cette initialisation, il faut faire le binding dans le code et non dans IB.
    - (void)bind:(NSString *)binding toObject:(id)observableController withKeyPath:(NSString *)keyPath options:(NSDictionary *)options

  • OmfraaxOmfraax Membre
    13:47 modifié #6
    Merci beaucoup !
    Ce que j'ai fait, j'ai initialisé dans mon myPlayer dans le -init  et ça marche ...

    Doit-on en déduire que l'établissement des bindings se fait entre ces deux méthodes ?
    Et même, à  quoi sert alors le –awakeFromNib ?

    Merci déjà  pour ces réponses, je ferai plus attention à  ces initialisations la prochaine fois.
  • Philippe49Philippe49 Membre
    13:47 modifié #7
    dans 1222076932:

    Doit-on en déduire que l'établissement des bindings se fait entre ces deux méthodes ?
    Et même, à  quoi sert alors le –awakeFromNib ?

    Ce qui est certain c'est le message awakeFromNib est envoyé après que le nib ait été désarchivé, et donc que les connections & bindings ait été installés.

    Le awakeFromNib sert à  des initialisations ultérieures avec le matériel établi justement par ce nib. Par exemple, pour ce qui te concerne, la solution de faire le binding dans le code.
  • Philippe49Philippe49 Membre
    13:47 modifié #8
    dans 1222083441:

    dans 1222076932:

    Doit-on en déduire que l'établissement des bindings se fait entre ces deux méthodes ?
    Et même, à  quoi sert alors le –awakeFromNib ?

    Ce qui est certain c'est le message awakeFromNib est envoyé après que le nib ait été désarchivé, et donc que les connections & bindings ait été installés.


    Voir Resource Programming Guide
Connectez-vous ou Inscrivez-vous pour répondre.