Donner à  ma classe (View) un accès à  ma classe (Model)

CrazyJoCrazyJo Membre
20:15 modifié dans API UIKit #1
Bonjour,

Je suis actuellement les cours de Stanford et j'en suis au premier TP nommée HelloPoly.

Je suis confronté au problème suivant , je n'arrive pas à  donner à  ma classe (View) un accès à  ma classe (Model) PolygonShape.

Le .h de Controller
@interface Controller : NSObject {<br />&nbsp; &nbsp; IBOutlet UIButton *decreaseButton;<br />&nbsp; &nbsp; IBOutlet UIButton *increaseButton;<br />&nbsp; &nbsp; IBOutlet UILabel *numberOfSidesLabel;<br />	IBOutlet PolygonView *polygonView;<br />	IBOutlet PolygonShape *polygon;<br />}[...]

le .h de PolygonView
@interface PolygonView : UIView {<br />	IBOutlet PolygonShape *polygon;<br />}<br />[...]<br />


Dans IB j'ai fait les liaisons suivantes :
voir ficher joint.

Et lorsque dans le .m de PolygonView je fais un nslog pour voir ce qu'il en est, je contate qu'il créé à  chaque fois une nouvelle instance de la classe PolygonShape lorsque que drawRect: est appelé.

Ca fait 3 jours que je bloque, commence à  en avoir marre.  :o :'(

Réponses

  • Philippe49Philippe49 Membre
    20:15 modifié #2
    Elle s'écrit comment ta méthode drawRect ?
  • Philippe49Philippe49 Membre
    20:15 modifié #3
    L'essai ci-joint fonctionne sans le désagrément que tu cites
  • CrazyJoCrazyJo Membre
    20:15 modifié #4
    Merci.

    Alors pour la méthode drawRect :
    - (void)drawRect:(CGRect)rect { <br />	NSLog(@&quot;DrawRect: has been called &quot;);<br />	NSLog(@&quot;var numberOfSides %i&quot;,polygon.numberOfSides);<br />	<br />	// Draw frame<br />	CGContextRef context = UIGraphicsGetCurrentContext();<br />	CGRect bounds = [self bounds];<br />	[[UIColor whiteColor]set];<br />	UIRectFill(bounds);<br />[...]<br />
    


    Appelée ici dans le .m de Controller :
    <br />- (IBAction)increase {<br />&nbsp; &nbsp; NSLog(@&quot;I'm in the increase method&quot;); <br />	polygon.numberOfSides++;<br />	self.updateInterface;<br />}<br />- (void)updateInterface {<br />	NSLog(@&quot;numberofsides: %i&quot;,polygon.numberOfSides);<br />	// Enable or not buttons<br />	if ( polygon.numberOfSides == polygon.maximumNumberOfSides&nbsp; ) {<br />		increaseButton.enabled = NO;<br />	} else if ( polygon.numberOfSides == polygon.minimumNumberOfSides) {<br />		decreaseButton.enabled = NO;<br />	} else {<br />		increaseButton.enabled = YES;<br />		decreaseButton.enabled = YES;<br />	}<br />	// Set the text of text label to indicate the current number of sides<br />	numberOfSidesLabel.text = [NSString stringWithFormat:@&quot;%i&quot;,polygon.numberOfSides];<br />	<br />	// View needs to be redrawn<br />&nbsp; &nbsp; [polygonView setNeedsDisplay];<br />}<br />
    


    LOG :
    2009-05-20 10:18:32.036 HelloPoly[371:20b] DrawRect: has been called
    2009-05-20 10:18:32.037 HelloPoly[371:20b] var numberOfSides 5
    2009-05-20 10:18:33.010 HelloPoly[371:20b] I'm in the decrease method
    2009-05-20 10:18:33.012 HelloPoly[371:20b] numberofsides: 3
    2009-05-20 10:18:33.013 HelloPoly[371:20b] DrawRect: has been called
    2009-05-20 10:18:33.013 HelloPoly[371:20b] var numberOfSides 5
    2009-05-20 10:18:33.378 HelloPoly[371:20b] I'm in the increase method
    2009-05-20 10:18:33.378 HelloPoly[371:20b] numberofsides: 4
    2009-05-20 10:18:33.379 HelloPoly[371:20b] DrawRect: has been called
    2009-05-20 10:18:33.380 HelloPoly[371:20b] var numberOfSides 5
    etc...

    On voit bien que var numberOfSides reste toujours à  5 alors que polygon est bien incrémenté/décrémenté dans la classe Controller. C'est quoi si PolygonView faisait tout le temps une nouvelle instance de PolygonShape lorsque la méthode drawRect: est appelée .

    Pour ton projet il y a une erreur :
    error: UIKit/UIKit.h: No such file or directory dans CrazyJo_Prefix.pch, je ne la comprends pas.

    Sinon tant qu'à  faire voici mon projet :
  • NseaProtectorNseaProtector Membre
    20:15 modifié #5
    Je reconnais là  un exemple du podcast de Stanford....
    Sans m'être attardé dessus , j'ai cru remarqué que tu inclémentes le nombre de face de ton polygon déclaré dans le controller.h, mais que la vue dessinait le polygon déclaré dans polygonView.h
    Peut-être une piste ....
  • Philippe49Philippe49 Membre
    mai 2009 modifié #6
    dans 1242807908:

    Pour ton projet il y a une erreur :
    error: UIKit/UIKit.h: No such file or directory dans CrazyJo_Prefix.pch, je ne la comprends pas.

    Cela signifie que tu n'as pas accès dans ton projet à  <UIKit/UIKit.h> et que le #import <UIKit/UIKit.h> qui se trouve le fichier Prefix.pch ne peut aboutir.
    [EDIT]C'est pas une erreur dans le projet, peut-être faut-il tout simplement régler le menu Active SDK (je dois être sous 3.0),  au pire recharger les framework là  où ils sont installés chez toi.

    rq : Dans mon projet, il reste un warning sans importance pour le fonctionnement, mais cela n'a rien à  voir avec l'erreur (grave) que tu signales ci-dessus. Cela n'empêche d'ailleurs pas le programme de fonctionner...

  • Philippe49Philippe49 Membre
    20:15 modifié #7
    Le programme que j'ai posté prouve que les objets PolygonShape ne peuvent pas se créer comme cela ex-nihilo. Celui qui est dans le xib est initialisé/instancié une fois et une seule lors du désarchivage du xib. Il faut que quelque part ton projet il y ait création d'un nouveau PolygonShape.
  • Philippe49Philippe49 Membre
    20:15 modifié #8
    Bon j'ai regardé ton code . Voici le bone :
    <br />- (void)awakeFromNib {<br />	polygon = [[PolygonShape alloc]initWithNumberOfSides:numberOfSidesLabel.text.integerValue minimumNumberOfSides:3 maximumNumberOfSides:12];<br />	NSLog(@&quot;My polygon: %@&quot;,polygon);<br />	self.updateInterface;<br />}
    


    Tu connectes dans IB ton outlet polygon, et tu le redéfinis dans awakeFromNib. ce sont deux instances différentes qui sont vues par ton controller et ta vue PolygonView. Supprimes

    polygon = [[PolygonShape alloc]initWithNumberOfSides:numberOfSidesLabel.text.integerValue minimumNumberOfSides:3 maximumNumberOfSides:12];

    et ta vie recommencera à  couler comme une rivière dans le Montana !



    remarque:  self.updateInterface cela marche, mais en ObjC, on écrit [self updateInterface]

  • NseaProtectorNseaProtector Membre
    20:15 modifié #9
    Ah oui je l'avais pas vu celui là , mais j'étais bien sur la voie quelque part ...
    Pour le self.updateInterface,
    il me semble que pour les @property se soit autorisé, se serait même une des améliorations du "language". enfin je crois...
  • Philippe49Philippe49 Membre
    mai 2009 modifié #10
    dans 1242807908:

    C'est quoi si PolygonView faisait tout le temps une nouvelle instance de PolygonShape lorsque la méthode drawRect: est appelée .


    Question de méthode : tu as bien senti que cela coinçait au sujet de l'instance de PolygonShape. Dès lors, il aurait été plus facile de choisir le log NSLog(@%@",polygon) dans les actions des boutons afin d'analyser l'évolution des instances de PolygonShape créées. Je pense que tu en serais arrivé à  la même conclusion que moi.
  • Philippe49Philippe49 Membre
    mai 2009 modifié #11
    dans 1242820657:

    Ah oui je l'avais pas vu celui là , mais j'étais bien sur la voie quelque part ...
    Pour le self.updateInterface,
    il me semble que pour les @property se soit autorisé, se serait même une des améliorations du "language". enfin je crois...


    En l'occurence il ne s'agit pas d'une property mais de l'appel d'une méthode -(void) updateInterface;
    self.updateInterface est une facilité syntaxique pour faire plaisir à  ceux viennent du Java, ce n'est pas une amélioration. Autant les property sont considérées par certains comme une amélioration, et je suis plutôt dans cette catégorie, autant l'appel de méthodes ne gagne rien à  cette écriture. 
  • NseaProtectorNseaProtector Membre
    20:15 modifié #12
    dans 1242821121:

    dans 1242820657:

    Ah oui je l'avais pas vu celui là , mais j'étais bien sur la voie quelque part ...
    Pour le self.updateInterface,
    il me semble que pour les @property se soit autorisé, se serait même une des améliorations du "language". enfin je crois...


    En l'occurence il ne s'agit pas d'une property mais de l'appel d'une méthode -(void) updateInterface;
    self.updateInterface est une facilité syntaxique pour faire plaisir à  ceux qui n'ont fait que du Java et jamais une bribe de C, ce n'est pas une amélioration  mais plutôt une régression. Autant les property sont considérées par certains comme une amélioration, et je suis plutôt dans cette catégorie, autant l'appel de méthodes ne gagne rien à  cette écriture. 

    Question de goût peut-être, même si c'est moins clair, à  taper c'est plus simple surtout dans la pénombre au lit avec quelqu'un qui dors à  côté... lol.
  • Philippe49Philippe49 Membre
    20:15 modifié #13
    Si on veut ... mais comment faire avec [myView setNeedsDisplay:YES]; en notation .  ?? Je trouve une certaine esthétique/clarté dans la notation entre crochets, on sait qui fait quoi, et pourquoi on introduit tel ou tel argument.
    Par contre, la notation point pour les méthodes est parfois intéressante dans l'utilisation des key-path.
    Mais ... je ne voudrais pas te réveiller  8--) ::) 

  • AliGatorAliGator Membre, Modérateur
    20:15 modifié #14
    +1 avec Philippe49... La notation "." a été introduite dans le but de faire des accès à  des propriétés, pour connaà®tre ou modifier l'état d'un objet par exemple. Pas pour faire des appels de méthodes.
    Certes sous le capot ça revient au même puisque l'accès à  une propriété toto consiste à  appeler le getter qui, par défaut, s'appelle du même nom que la propriété, à  savoir "toto". Mais conceptuellement, c'est quand même pas super et pas uniforme avec les autres appels de méthodes prenant, eux, des paramètres...
    Après, c'est sûr, ça marche, mais bon...
  • CrazyJoCrazyJo Membre
    20:15 modifié #15
    dans 1242820203:

    Bon j'ai regardé ton code . Voici le bone :
    <br />- (void)awakeFromNib {<br />	polygon = [[PolygonShape alloc]initWithNumberOfSides:numberOfSidesLabel.text.integerValue minimumNumberOfSides:3 maximumNumberOfSides:12];<br />	NSLog(@&quot;My polygon: %@&quot;,polygon);<br />	self.updateInterface;<br />}
    


    Tu connectes dans IB ton outlet polygon, et tu le redéfinis dans awakeFromNib. ce sont deux instances différentes qui sont vues par ton controller et ta vue PolygonView. Supprimes

    polygon = [[PolygonShape alloc]initWithNumberOfSides:numberOfSidesLabel.text.integerValue minimumNumberOfSides:3 maximumNumberOfSides:12];

    et ta vie recommencera à  couler comme une rivière dans le Montana !

    remarque:  self.updateInterface cela marche, mais en ObjC, on écrit [self updateInterface]

    <3 C'est ça !<br />
    J'ai compris mon erreur : je ne savais pas qu'Interface Builder créait à  nouveau une instance de PolygonShape du coup je comprends mieux la confusion qu'il y a eu entre les 2 instances.

    Je vais maintenant pouvoir avancer plus loin dans le cours de Stanford.

    Concernant la dot syntaxe merci pour la précision. J'admets que c'est nettement moins compréhensible lorsqu'il n'y a pas les [] lors de l'appels de méthodes.







  • SmySmy Membre
    20:15 modifié #16
    CrazyJo, j'ai une version qui fonctionne si tu veux, elle est légèrement différente de la tienne. Je peux te l'envoyer par email en MP.

    [Edit] Nos messages se sont croisés, tu as donc trouvé la réponse...
  • SmySmy Membre
    20:15 modifié #17
    Je profite de ce sujet pour poser une question sur les outlets dans IB.

    Comment fonctionne IB pour que le PolygonShare *polygon de Controller et celui de PolygonView soient les mêmes, et non pas deux instances ?

    Je vois bien la mise en place de la liaison dans IB, mais comment au final cela fonctionne t'il ? C'est plutôt une question d'Objective C pour le coup.

    J'ai des siècles de programmation procédurale en C :), mais de bien belles questions en Objective C...
  • AliGatorAliGator Membre, Modérateur
    20:15 modifié #18
    dans 1242852827:
    Comment fonctionne IB pour que le PolygonShare *polygon de Controller et celui de PolygonView soient les mêmes, et non pas deux instances ?

    Je vois bien la mise en place de la liaison dans IB, mais comment au final cela fonctionne t'il ? C'est plutôt une question d'Objective C pour le coup.
    hop hop hop, mon explication de l'époque dans un autre sujet
  • Philippe49Philippe49 Membre
    20:15 modifié #19
    dans 1242850285:

    J'ai compris mon erreur : je ne savais pas qu'Interface Builder créait à  nouveau une instance de PolygonShape du coup je comprends mieux la confusion qu'il y a eu entre les 2 instances.

    C'est le B.A.BA de la programmation en liaison avec Interface Builder .
  • NseaProtectorNseaProtector Membre
    20:15 modifié #20
    dans 1242850370:

    CrazyJo, j'ai une version qui fonctionne si tu veux, elle est légèrement différente de la tienne. Je peux te l'envoyer par email en MP.

    Et pourquoi ne pas en faire profiter a tout le monde ?
  • SmySmy Membre
    20:15 modifié #21
    dans 1242853010:

    dans 1242852827:
    Comment fonctionne IB pour que le PolygonShare *polygon de Controller et celui de PolygonView soient les mêmes, et non pas deux instances ?

    Je vois bien la mise en place de la liaison dans IB, mais comment au final cela fonctionne t'il ? C'est plutôt une question d'Objective C pour le coup.
    hop hop hop, mon explication de l'époque dans un autre sujet


    Merci AliGator. C'est donc la "désérialisation" du nib qui crée les instances et fait les liaisons.

    dans 1242855320:

    dans 1242850370:

    CrazyJo, j'ai une version qui fonctionne si tu veux, elle est légèrement différente de la tienne. Je peux te l'envoyer par email en MP.

    Et pourquoi ne pas en faire profiter a tout le monde ?


    Hop, attachée à  ce message.
  • NseaProtectorNseaProtector Membre
    20:15 modifié #22
    Merci.
    Ce qui est marrant c'est pas la différence mais plutôt la ressemblance, vous vous êtes inspiré de quelque chose ? Un des épisodes de Stanford ?
  • CrazyJoCrazyJo Membre
    20:15 modifié #23
    dans 1242870209:

    Merci.
    Ce qui est marrant c'est pas la différence mais plutôt la ressemblance, vous vous êtes inspiré de quelque chose ? Un des épisodes de Stanford ?

    Oui.

    Lecture 3 et 4 des cours de Stanford : http://www.stanford.edu/class/cs193p/cgi-bin/index.php  8--)
    dans 1242853010:

    dans 1242852827:
    Comment fonctionne IB pour que le PolygonShare *polygon de Controller et celui de PolygonView soient les mêmes, et non pas deux instances ?

    Je vois bien la mise en place de la liaison dans IB, mais comment au final cela fonctionne t'il ? C'est plutôt une question d'Objective C pour le coup.
    hop hop hop, mon explication de l'époque dans un autre sujet

    Oula quelle réponse ! Ca a l'air super complet, je vais lire ça immédiatement !

    Merci à  vous tous !
  • SmySmy Membre
    20:15 modifié #24
    dans 1242870209:

    Merci.
    Ce qui est marrant c'est pas la différence mais plutôt la ressemblance, vous vous êtes inspiré de quelque chose ? Un des épisodes de Stanford ?


    C'est un des exercices liés aux cours CS139P de Standford. Comme nous partons des mêmes cours, et de la même progression d'exercice en exercice, la ressemblance est en fait normale.

    Pour les autres débutants en programmation iPhone, ces cours sont vraiment très bons, très progressifs. J'avais préalablement lu une grande partie du Zdziarski, mais il n'aborde pas du tout IB dans son livre.
  • Philippe49Philippe49 Membre
    20:15 modifié #25
    Franchement, je ne trouve pas top cette version de HelloPoly
    Je vous livre la mienne dans quelques instants ...
  • Philippe49Philippe49 Membre
    20:15 modifié #26
    Voilou.

    - Une catégorie pour fabriquer le polygone régulier sous la forme d'un CGPathRef
    - La suppression de tous ces va et vient entre des NSArray et des NSValue qui sont une perte de temps.
    - La suppression de ce switch à  10 valeurs du case.
    - La suppression de properties inutiles dans la classe PolygonShape.
    - L'utilisation des fonctions sur les CGRect

    ...



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