Push d'un navigateur sur clic UIImageView

allianallian Membre
avril 2009 modifié dans API UIKit #1
Bonjour,

je suis nouveau en programmation Objective-C et je dois faire une boucle où je crée à  chaque fois une nouvelle instance de ma classe et je butte sur le nom de cette instance. Si je met un nom comme maVar, bien évidemment je crée toujours le même objet donc en fin de compte j'en ai qu'un seul.

Je voudrais alors faire comme je fait d'habitude avec d'autres langages, c'est à  dire concatener par exemple un nom de var fixé avec un entier du genre :
premier tour de boucle : maVar1
deuxieme tout de boucle : maVar2
...

J'ai bien un NSString qui contient ce nom mais je ne sais pas comment le passer en tant que nom de variable :

J'ai essayé ça : (MaClasse *)[monString] mais ca ne marche pas.
Quelqu'un pourrait il m'aider ?

merci d'avance
«1

Réponses

  • Philippe49Philippe49 Membre
    18:19 modifié #2
    En général, on n'a pas besoin de faire ce genre de chose.

    Si tu fais une boucle avec une variable déclarée en interne, la portée de cette variable est limitée à  la boucle :

    NSMutableArray * array=[NSMutableArray array];<br />for(int i=0;i&lt;10;i++) {<br />    NSString * string=[NSString stringWithFormat:@&quot;numéro %d&quot;,i];<br />    [array addObject:string];<br />}
    


    permet de créer effectivement 10 NSString différentes .

    cela répond-il à  ta question ?
  • Philippe49Philippe49 Membre
    18:19 modifié #3
    L'autre solution c'est la macro du langage C avec ## mais je pense que tu es en train de compliquer une situation simple.
  • allianallian Membre
    18:19 modifié #4
    je vous explique mieux, je développe pour iPhone, et le but de ma boucle est de créer des instances d'un même UIViewController afin d'avoir de multiples instances de ma classe dans une vue parent.

    voici mon code :

    CGFloat x = 50;<br />	CGFloat y = 50;<br />	int i,j;<br />	NSString *monTagN = @&quot;aTag&quot;;<br />	NSString *stringI;<br />	<br />	NSArray *monTab = [[NSArray alloc] initWithObjects: @&quot;huh&quot;, @&quot;hih&quot;, @&quot;hoh&quot;, nil];<br />	j = [monTab count];<br />	<br />	for (i = 1; i &lt;= j; i = i + 1)<br />	{<br />		<br />		stringI = [NSString stringWithFormat:@&quot;%d&quot;, i];<br />		NSString *monTag = [monTagN stringByAppendingString:stringI];<br />		MyTag *monTag = [[MyTag alloc] init];<br />		monTag.myName = @&quot;Surf&quot;;<br />		monTag.urlImage = @&quot;http://qe08/upload/videos//ID-119-2-illunews.jpg&quot;;<br />		monTag.x = x + 50;<br />		monTag.y = y + 50;<br />		NSLog(@&quot;quel boucle %i&quot;,i);<br />		[self.view insertSubview:monTag.view atIndex:i];<br />	<br />	}
    


    le problème vient du fait que si je garde le même nom pour mon instance de classe, il efface les précédentes et en fin de compte je me retrouve avec une seule instance, la dernière.
    Ceci vient du fait que chaque vue doit exister afin d'être affichée et que du coup elle persiste(retain).

    Bref je pensais qu'en faisant comme par exemple maVar + i pour le nom de ma variable ca passerait. Un peu comme en javascript.

    Si ce n'est pas possible comment faire pour avoir des noms de variables différents à  chaque tour de boucle.

    J'avais pensé à  un tableau mais ca revient un peu au meme je ne sais pas comment donner le contenu de mon tableau au nom de ma variable
    merci
  • Philippe49Philippe49 Membre
    avril 2009 modifié #5
    dans 1239290124:

    je vous explique mieux, je développe pour iPhone, et le but de ma boucle est de créer des instances d'un même UIViewController afin d'avoir de multiples instances de ma classe dans une vue parent.


    Tu fais un NSMutableArray viewControllers contenant ces UIViewController.
    et tu les appelles ensuite

    NSMutableArray * viewControllers=[NSMutableArray array];<br />for(int i=0;i&lt;10;i++) {<br />      MyUIViewController * aViewController=[[MyUIViewController alloc] init...;<br />&nbsp; &nbsp; &nbsp; // configurer<br />      [viewControllers addObject: aViewController];<br />}<br />
    

    et ce que tu voudrais appeler viewControllers_8 est appelé par
          [viewControllers objectAtIndex: 8];


    Encore une fois il y a une solution par les macros, mais ce n'est pas ce qui se fait traditionnellement.
  • allianallian Membre
    18:19 modifié #6
    merci pour ta solution mais je ne pense pas qu'elle résout mon probleme, car je me retrouve du coup avec un tableau avec mes controlleurs d'accord. Mais ils ont tous le même nom et quand je fais le addSubview:monViewControleur.view c'est pareil j'ajoute toujours le meme.

    je sais vraiment pas comment faire... c'est si simple dans d'autres langages
  • Philippe49Philippe49 Membre
    18:19 modifié #7
    dans 1239291934:

    addSubview:monViewControleur.view c'est pareil j'ajoute toujours le meme.

    je sais vraiment pas comment faire... c'est si simple dans d'autres langages


    Fais simplement
    [ ....  addSubview:[[viewControllers objectAtIndex:i] view] ]

    ou plus proprement au niveau lecture du code  :

    currentViewController=[viewControllers objectAtIndex:i];
    [ ....  addSubview: currentViewController.view ]


  • CéroceCéroce Membre, Modérateur
    18:19 modifié #8
    Philippe t'as donné toute la solution. Arrête de chercher à  faire comme en Javascript, ObjC ne fonctionne pas du tout de la même façon.

    Pour corriger le code de Philippe qui a fait un petit oubli:
    NSMutableArray * viewControllers=[NSMutableArray array];<br />for(int i=0;i&lt;10;i++) {<br />&nbsp; &nbsp; &nbsp; MyUIViewController * aViewController=[[MyUIViewController alloc] init...;<br />&nbsp; &nbsp; &nbsp; // configurer<br />&nbsp; &nbsp; &nbsp; [viewControllers addObject: aViewController];<br />&nbsp; &nbsp; &nbsp; [aViewController release];&nbsp; //&nbsp; &lt;- Les Arrays envoient un [retain] aux objets insérés<br />}
    


  • Philippe49Philippe49 Membre
    18:19 modifié #9
    Par ailleurs ton code initial crée effectivement j view controllers différents, et les j vues sont effectivement insérées sur la vue principale. Le problème avec ce code c'est que tu perds les view controllers.
  • allianallian Membre
    18:19 modifié #10
    ok ok je vais essayer avec ces tableaux, j'espère que ça va fonctionner.
    si j'ai bien compris mon ajout de controlleurs doit alors se faire en dehors de la boucle ?

    <br />	CGFloat x = 50;<br />	CGFloat y = 50;<br />	int i,j;<br /><br />	NSArray *monTab = [[NSArray alloc] initWithObjects: @&quot;huh&quot;, @&quot;hih&quot;, @&quot;hoh&quot;, nil];<br />	j = [monTab count];<br />	<br />	NSMutableArray *viewControllers = [NSMutableArray array];<br />	<br />	for (i = 1; i &lt;= j; i = i + 1)<br />	{<br />		MyTag *monTag = [[MyTag alloc] init];<br />		monTag.myName = @&quot;Surf&quot;;<br />		monTag.urlImage = @&quot;http://qe08/upload/videos//ID-119-2-illunews.jpg&quot;;<br />		monTag.x = x + 50;<br />		monTag.y = y + 50;<br />		<br />		[viewControllers addObject: monTag];<br /><br />	}<br />	<br />	[self.view addSubview:[[viewControllers objectAtIndex:i] view]];<br />	<br />&nbsp; &nbsp; [super viewDidLoad];<br />
    
  • Philippe49Philippe49 Membre
    avril 2009 modifié #11
    dans 1239293355:

    ok ok je vais essayer avec ces tableaux, j'espère que ça va fonctionner.
    si j'ai bien compris mon ajout de controlleurs doit alors se faire en dehors de la boucle ?

    Non

    <br />	CGFloat x = 50;<br />	CGFloat y = 50;<br />	int i,j;<br /><br />	NSArray *monTab = [[NSArray alloc] initWithObjects: @&quot;huh&quot;, @&quot;hih&quot;, @&quot;hoh&quot;, nil];<br />	j = [monTab count];<br />	<br />	NSMutableArray *viewControllers = [NSMutableArray array];<br />	<br />	for (i = 1; i &lt;= j; i = i + 1)<br />	{<br />		MyTag *monTag = [[MyTag alloc] init];<br />		monTag.myName = @&quot;Surf&quot;;<br />		monTag.urlImage = @&quot;http://qe08/upload/videos//ID-119-2-illunews.jpg&quot;;<br />		monTag.x = x + 50;<br />		monTag.y = y + 50;<br />		<br />		[viewControllers addObject: monTag];<br /><br />// *********************<br />		[self.view addSubview:monTag.view];<br />		[monTag release];<br />		<br />// *********************<br /><br />	}<br />	<br />	<br />&nbsp; &nbsp; [super viewDidLoad];<br />
    


    et si après tu as besoin de manipuler de nouveau tes vues ou contrôleurs, tu les atteints par [viewControllers objectAtIndex:i]
  • Philippe49Philippe49 Membre
    18:19 modifié #12
    Il serait par ailleurs souhaitable que la variable viewControllers soit définie comme variable d'instance et non à  l'intérieur de la méthode, sinon tu la perds à  la sortie de la méthode

    @interface ....  {<br />        NSMutableArray * viewControllers;<br />} <br /><br />@implementation ...<br />...<br />-(void) viewDidLoad {<br />	CGFloat x = 50;<br />	CGFloat y = 50;<br />	int i,j;<br /><br />	NSArray *monTab = [[NSArray alloc] initWithObjects: @&quot;huh&quot;, @&quot;hih&quot;, @&quot;hoh&quot;, nil];<br />	j = [monTab count];<br />	<br />/************************************<br />	viewControllers = [[NSMutableArray alloc] init];<br />/************************************<br />	<br />	for (i = 1; i &lt;= j; i = i + 1)<br />// etc ...<br />}<br />
    



  • allianallian Membre
    18:19 modifié #13
    merci beaucoup je comprends mieux, du coup meme si ils sont "perdus" apres etre sorti de la boucle on les a toujours dans le tableau car lui est declaré en dehors de celle ci.

    La je n'est plus d'erreur ni de plantage par contre plus rien ne s'affiche alors que si je fais le meme code en dehors de la boucle avec à  la place de i par exemple 1 cela m'affiche une instance de ma classe....  :(
  • Philippe49Philippe49 Membre
    18:19 modifié #14

    Comment est créée la vue dans la classe MyTag ?
  • schlumschlum Membre
    18:19 modifié #15
    Il serait peut-être bon de lire un livre sur l'Objective-C et Cocoa avant de se lancer tête perdue dans du développement iPhone en essayant de faire du JavaScript non ?

    Comme " Cocoa par la Pratique " de Hillegass par exemple...
  • allianallian Membre
    18:19 modifié #16
    bé j'en est lu plus d'un de livre et je me lance pas la tête perdue dans le dev, j'ai juste fait une reference a js pour faire comprendre ce que j'essayais de faire loin de moi l'idée de programmer de la meme facon.
    Bref ma vue est comme ceci

    le .h :

    #import &lt;UIKit/UIKit.h&gt;<br /><br /><br />@interface MyTag : UIViewController {<br />	<br />	NSString *myName;<br />	NSString *urlImage;<br />	IBOutlet UIImageView *myTagImage;<br />	IBOutlet UILabel *myTagName;<br />	CGFloat x;<br />	CGFloat y;<br /><br />}<br /><br />@property(nonatomic) CGFloat x;<br />@property(nonatomic) CGFloat y;<br />@property(nonatomic, retain) NSString *myName;<br />@property(nonatomic, retain) NSString *urlImage;<br />@property(nonatomic, retain) IBOutlet UIImageView *myTagImage;<br />@property(nonatomic, retain) IBOutlet UILabel *myTagName;<br /><br />@end
    



    et son implémentation

    #import &quot;MyTag.h&quot;<br />#import &quot;NavigationViewController.h&quot;<br />#import &quot;TagCloud.h&quot;<br /><br /><br />@implementation MyTag<br />@synthesize myTagName, myTagImage, urlImage, myName, x, y;<br /><br /><br /><br />// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.<br />- (void)viewDidLoad {<br />	<br />	NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:urlImage]];<br />	UIImage *myCurrentImage = [[UIImage alloc] initWithData:imageData];<br />	myTagImage.image =&nbsp; myCurrentImage;<br />	myTagImage.contentMode = UIViewContentModeScaleAspectFit;<br />	myTagName.text = myName;<br />	myTagImage.userInteractionEnabled = YES;<br /><br />	CGPoint monCentre = CGPointMake(x, y);<br />	self.view.center = monCentre;<br /><br />&nbsp; &nbsp; [super viewDidLoad];<br />}<br /><br /><br />// Finger touches to the Image View will start the movie playing<br />- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {<br />&nbsp; &nbsp; UITouch* touch = [touches anyObject];<br />&nbsp; &nbsp; if (touch.phase == UITouchPhaseBegan)<br />&nbsp; &nbsp; {<br />		<br /><br /><br />&nbsp; &nbsp; }&nbsp; &nbsp; <br />}<br /><br /><br />- (void)dealloc {<br />&nbsp; &nbsp; [super dealloc];<br />}<br /><br /><br />@end<br />
    
  • Philippe49Philippe49 Membre
    18:19 modifié #17
    dans 1239349027:

    bé j'en est lu plus d'un de livre et je me lance pas la tête perdue dans le dev, j'ai juste fait une reference a js pour faire comprendre ce que j'essayais de faire loin de moi l'idée de programmer de la meme facon.

    M'enfin bon, là  manifestement tu n'as de pas grandes références sur le dev iPhone et sur l'obj-C ... et le conseil de Schlum est du pur bon sens : Il est difficile d'aborder Obj-C/Cocoa/Cocoa Touch uniquement avec des tutos ou des références sur le web comme on peut le faire pour le C  ou d'autres langages très répandus.

    dans 1239349027:

    // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
    - (void)viewDidLoad {
    ....


    Pour utiliser viewDidLoad il faut un xib associé, "MyTag.xib" par exemple, et la création se fait alors par
    [[MyTag alloc] initWithNibName:@MyTag bundle:nil]


  • allianallian Membre
    18:19 modifié #18
    j'ai bien un MyTag.xib qui contient une imageView et un UiLabel, auxquels je fais référence avec mes deux IBOutlet.
    Dans ma méthode viewDidLoad () je fais donc les init nécessaires à  ma classe mais je ne vois pas pourquoi j'ai besoin de faire un initWithNibName puisque dans Interface Builder j'ai dit que ma classe est associée avec le nib MyTag.xib
    Mon probleme viendrait il de la ? Est ce que je dois donc effacer le lien dans IB et utiliser la méthode iniWithNibName ?

    merci encode de votre aide

    - (void)viewDidLoad {<br />	<br />	NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:urlImage]];<br />	UIImage *myCurrentImage = [[UIImage alloc] initWithData:imageData];<br />	myTagImage.image =&nbsp; myCurrentImage;<br />	myTagImage.contentMode = UIViewContentModeScaleAspectFit;<br />	myTagName.text = myName;<br />	myTagImage.userInteractionEnabled = YES;<br /><br />	CGPoint monCentre = CGPointMake(x, y);<br />	self.view.center = monCentre;<br /><br />&nbsp; &nbsp; [super viewDidLoad];<br />}
    
  • Philippe49Philippe49 Membre
    avril 2009 modifié #19
    Ah je crois comprendre : tu as un controller MyTag dans le xib principal ?

    Cela ne peut pas marcher ainsi.
  • allianallian Membre
    18:19 modifié #20
    mon xib principal est TagCloud.xib et sa classe associée est la suivante :

    #import &quot;TagCloud.h&quot;<br />#import &quot;MyTag.h&quot;<br /><br />@implementation TagCloud<br /><br />// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.<br />- (void)viewDidLoad {<br />	<br />	CGFloat x = 50;<br />	CGFloat y = 50;<br />	int i,j;<br />	<br />	NSArray *monTab = [[NSArray alloc] initWithObjects: @&quot;huh&quot;, @&quot;hih&quot;, @&quot;hoh&quot;, nil];<br />	j = [monTab count];<br />	<br />	NSMutableArray *viewControllers = [NSMutableArray array];<br />	<br />	for (i = 1; i &lt;= j; i = i + 1)<br />	{<br />		MyTag *monTag = [[MyTag alloc] init];<br />		monTag.myName = @&quot;Surf&quot;;<br />		monTag.urlImage = @&quot;http://qe08/upload/videos//ID-119-2-illunews.jpg&quot;;<br />		monTag.x = x + 50;<br />		monTag.y = y + 50;<br />		<br />		[viewControllers addObject: monTag];<br />		<br />		// *********************<br />		[self.view insertSubview:monTag.view atIndex:i];<br />		//[monTag release];<br />	}<br />	<br />&nbsp; &nbsp; [super viewDidLoad];<br />}<br /><br /><br />- (void)didReceiveMemoryWarning {<br />&nbsp; &nbsp; [super didReceiveMemoryWarning]; // Releases the view if it doesn&#39;t have a superview<br />&nbsp; &nbsp; // Release anything that&#39;s not essential, such as cached data<br />}<br /><br /><br />- (void)dealloc {<br />&nbsp; &nbsp; [super dealloc];<br />}<br /><br /><br />@end<br />
    


  • Philippe49Philippe49 Membre
    18:19 modifié #21
    Si tu veux de multiples exemplaires de Mytag, il faut supprimer le MyTag dans le xib, ainsi que l'IBOutlet correspondant. Puis dans ta boucle de créations, utiliser initWithNibName.
  • allianallian Membre
    18:19 modifié #22
    je n'ai pas de MyTag dans mon xib pere. Le fichier TagCloud.xib qui devra contenir toutes mes instances de la classe MyTag est vide.


    #import &lt;UIKit/UIKit.h&gt;<br /><br /><br /><br />@interface TagCloud : UIViewController {<br /><br />}<br /><br /><br /><br />@end<br />
    


    je n'ai pas non plus de IBOutlet
  • Philippe49Philippe49 Membre
    18:19 modifié #23
    Il faut bien que la vue associée à  MyTag soit définie quelque part. Avec viewDidLoad, on fait cela en général avec un xib qui configure cette vue.

    1) Fait un clic droit sur les resources, add>new file et choisis view.xib dans les propositions.

    2) Double-clic sur ce xib

    3) Sélectionne File's Owner, et dans le panel Identity de IB (le dernier) indique la class MyTag dans le champ Class Identity

    4) Clic droit sur File's Owner, et tire une ligne de l'IBOutlet view à  la vue proprement dite : cela dit que la vue du File's owner, en l'occurence un view controller Mytag est configurée comme l'est cette vue.



  • allianallian Membre
    18:19 modifié #24
    merci beaucoup de ton aide mais cela avait déjà  était fait.

    image1rki.png
  • schlumschlum Membre
    18:19 modifié #25
    dans 1239349027:

    bé j'en est lu plus d'un de livre et je me lance pas la tête perdue dans le dev, j'ai juste fait une reference a js pour faire comprendre ce que j'essayais de faire loin de moi l'idée de programmer de la meme facon.


    Cocoa / Objective-C, ne n'est pas qu'un langage de programmation, c'est une API basée sur des design patterns assez spécifiques qu'il faut connaà®tre... En gros c'est presque une philosophie. Elle est difficile à  appréhender " comme ça ".
    Le livre que je t'ai proposé est une référence du genre.
  • schlumschlum Membre
    18:19 modifié #26
    dans 1239287683:

    Je voudrais alors faire comme je fait d'habitude avec d'autres langages, c'est à  dire concatener par exemple un nom de var fixé avec un entier du genre :
    premier tour de boucle : maVar1
    deuxieme tout de boucle : maVar2
    ...


    En tout cas, ça on peut faire la même chose avec un NSMutableDictionary

    int i;<br />NSMutableDictionary *test = [NSMutableDictionary dictionary];<br />for(i=0;i&lt;10;++i)<br />&nbsp; &nbsp; [test setObject:[NSNumber numberWithInt:i] forKey:[NSString stringWithFormat:@&quot;maVar%d&quot;,i]];
    


    Mais l'indirection est une très mauvaise pratique de programmation.
  • Philippe49Philippe49 Membre
    18:19 modifié #27
    dans 1239355833:

    merci beaucoup de ton aide mais cela avait déjà  était fait.


      [[MyTag alloc] initWithNibName:@MyTag bundle:nil]    >:)   8--)
  • allianallian Membre
    18:19 modifié #28
    merci pour ton conseil, des livres j'en est lu plusieurs et j'ai compris leur contenu mais une fois qu'il faut faire des applications complexes c'est pas la même chose...

    j'ai lu que des livres américains comme "Beginning iPhone Development", "The iPhone Developper's cookbook" et "Programming in Objective C 2.0" et ils m'ont aidé car je suis vraiment nouveau dans la programmation mac, je ne suis qu'étudiant après tout :D et je suis beaucoup plus calé en prog web qu'en C ou Java, du coup c'est vraiment tout nouveau pour moi et comme la je suis en stage justement pour développer une appli iPhone j'ai du m'y mettre.

    Bref tout ça pour dire que je galère un peu mais qu'au fur et à  mesure cava un peu mieux notamment grâce à  vos conseils.

    Donc si quelqu'un a une idée du pourquoi je ne peut pas afficher plusieurs instances de ma fameuse vue ou alors une autre solution je vous en remercie

  • schlumschlum Membre
    18:19 modifié #29
    D'où " Cocoa par la pratique " qui fait vraiment des chapitres avec des développement d'applications concrètes pour illustrer les concepts  :P
    Pas mal de développeurs ici l'ont lu pour commencer dans le Cocoa et font des applications complexes sans problème  :)

    (mais promis, j'ai pas d'actions chez l'éditeur  ;D)
  • allianallian Membre
    18:19 modifié #30
    :)
    je n'en doute pas  :kicking:

    je vais voir si je peut me le procurer mais pour le moment je dois tout de même essayer de résoudre mon problème car le temps tourne.. :-\\

  • schlumschlum Membre
    18:19 modifié #31
    dans 1239353462:

    Si tu veux de multiples exemplaires de Mytag, il faut supprimer le MyTag dans le xib, ainsi que l'IBOutlet correspondant. Puis dans ta boucle de créations, utiliser initWithNibName.


    ça c'est si on veut charger plusieurs fois le .xib
    Si on veut mettre plusieurs fois une vue dans une autre vue, c'est plus facile, il suffit d'allouer/initialiser la vue, de setter son frame et son bounds et d'utiliser "addSubview"
Connectez-vous ou Inscrivez-vous pour répondre.