Lien NSObject et UIViewController

Bonjour



J'ai un petit problème de lien entre deux classes NSObject (Liste) et UIViewController (ViewController). En fait, depuis ma UIViewController, j'appelle une méthode "faireQuelqueChose" de Liste qui change un NSString (nom) de ViewController. Après l'appel de cette méthode, j'affiche le nom, qui est renvoyé, dans la console. Le problème est que mon NSString est (null). Voici le code :



ViewController.h
<br />
@interface ViewController : UIViewController<br />
@property NSString *nom;<br />
@end<br />




ViewController.m
<br />
#import &quot;ViewController.h&quot;<br />
#import &quot;Liste.h&quot;<br />
@implementation ViewController<br />
@synthesize nom;<br />
- (void)viewDidLoad {<br />
	[super viewDidLoad];<br />
}<br />
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {<br />
	Liste *liste = [[Liste alloc]init];<br />
	[liste faireQuelqueChose];<br />
	NSLog(@&quot;%@&quot;, nom);<br />
}<br />




Liste.h
<br />
@interface Liste : NSObject<br />
-(void)faireQuelqueChose;<br />
@end<br />




Liste.m
<br />
#import &quot;Liste.h&quot;<br />
#import &quot;ViewController.h&quot;<br />
@implementation Liste<br />
<br />
-(void)faireQuelqueChose {<br />
	ViewController *vc = [[ViewController alloc] init];<br />
	vc.nom = @&quot;Paul&quot;;<br />
}<br />
@end<br />




Je ne comprend pas pourquoi mon NSString nom est nul dans ma console. Quelqu'un aurait-il une idée sur la question ?



Merci ! image/smile.png' class='bbc_emoticon' alt=':)' />

Réponses

  • tu doit mettre nom dans une autre variable pour la transmettre `cree une variable dans la liste .h et transfere le VC.nom a cette variable

    que tu le recuper dans le viewController avec list.string par exemple et la tu doit mettre nom=liste.STRING

    SI j'ai bien compris ton code ??
  • <br />
    ViewController *vc = [[ViewController alloc] init];<br />
    




    Visibilité limitée à  ta fonction.



    Ton Liste ne devrait-il pas ressembler plutôt à  ceci :


    <br />
    -(void)faireQuelqueChose:(ViewController *)myCustomViewController {<br />
    		myCustomViewController.nom = @&quot;Paul&quot;;<br />
    }<br />
    




    ?
  • <br />
    #import &quot;ViewController.h&quot;<br />
    #import &quot;liste.h&quot;<br />
    @interface ViewController ()<br />
    @end<br />
    @implementation ViewController<br />
    @synthesize nom;<br />
    - (void)viewDidLoad<br />
    {<br />
        [super viewDidLoad];<br />
    // Do any additional setup after loading the view, typically from a nib.<br />
    }<br />
    - (void)didReceiveMemoryWarning<br />
    {<br />
        [super didReceiveMemoryWarning];<br />
        // Dispose of any resources that can be recreated.<br />
    }<br />
    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {<br />
        liste *Liste = [[liste alloc]init];<br />
        [Liste faireQuelqueChose];<br />
        nom=Liste.string;<br />
        NSLog(@&quot;%@&quot;, nom);<br />
    }<br />
    @end<br />
    

    <br />
    #import &lt;UIKit/UIKit.h&gt;<br />
    @interface ViewController : UIViewController<br />
    @property NSString *nom;<br />
    @end<br />
    <br />
    

    <br />
    #import &lt;Foundation/Foundation.h&gt;<br />
    #import &quot;ViewController.h&quot;<br />
    @interface liste : NSObject<br />
    @property NSString *string;<br />
    -(void)faireQuelqueChose;<br />
    @end<br />
    

    <br />
    //<br />
    #import &quot;liste.h&quot;<br />
    @implementation liste<br />
    @synthesize string;<br />
    -(void)faireQuelqueChose {<br />
        ViewController *vc = [[ViewController alloc] init];<br />
        vc.nom = @&quot;Paul&quot;;<br />
        string=vc.nom;<br />
    }<br />
    @end<br />
    

    <br />
    2012-12-16 14:57:01.451 test[5836:c07] Paul<br />
    2012-12-16 14:57:03.013 test[5836:c07] Paul<br />
    
  • J'ai testé les deux solution et les deux marchent ! Par contre, dans la solution de Kubernan, je ne vois pas se qui change entre mon code et le tient, ça revient à  dire la même chose non ? Alors pourquoi mon code ne marche pas ?

    Merci pour vos réponses ! image/smile.png' class='bbc_emoticon' alt=':)' />
  • AliGatorAliGator Membre, Modérateur
    Le problème c'est que tu recrées des nouveaux objets à  chaque fois, au lieu de changer les propriétés de tes objets existants.

    Donc la solution est celle de Kubernan, à  savoir passer l'objet à  modifier en paramètre de la méthode faireQuelqueChose, pour que cette méthode change cet objet, au lieu d'en créer un nouveau qui va être oublié peu après et n'aura aucun rapport avec ton objet objet initial.



    C'est comme si tu décidais d'avoir une méthode "peindre:" pour peindre une voiture en rouge.

    Le but est d'apporter ta voiture au carrossier (passer la voiture en paramètre de la fonction "peindre:" de l'objet "Carrossier") pour qu'il peigne ta voiture en rouge.

    Or avec du code similaire au tien, pour faire le parallèle, tu es en train de demander au carrossier "peint moi une voiture en rouge" sans lui dire laquelle, et l'implémentation que tu as mis fait que ton carrossier va acheter une nouvelle voiture (= ton "alloc/init" qui créer un nouvel objet), va ensuite peindre cette nouvelle voiture en rouge (équivalent de ton vc.nom = @Paul), puis va mettre cette voiture à  la casse (= dans ton code, le vc créé et modifié n'est plus utilisé ensuite nulle part et tombe aux oubliettes). Donc ton carrossier aura créé une nouvelle voiture, l'aura peinte en rouge, puis l'aura jeté... et au final n'aura pas touché à  ta voiture à  toi qui sera toujours de sa couleur d'origine...



    Il faut sans doute que tu revois les concepts de Classe et d'Instance de classe pour comprendre la différence entre créer une nouvelle instance et passer un objet existant, et comprendre qu'une classe n'est qu'un modèle / moule pour créer des nouveaux objets indépendants les uns des autres.
  • est ce que le mien est correct aussi image/huh.gif' class='bbc_emoticon' alt='???' />

    niveau MVC et POO
  • Merci Ali pour ton explication très claire ! Je vais revoir ça.
  • AliGatorAliGator Membre, Modérateur
    'hamidphone' a écrit:


    est ce que le mien est correct aussi image/huh.gif' class='bbc_emoticon' alt='???' />

    niveau MVC et POO
    Pas vraiment non. C'est même une conception bizarre et inefficace que tu as là .



    Tu crées des nouveaux objets pour affecter une valeur à  leur une propriété pour ensuite recopier cette valeur dans une variable d'instance.

    Déjà  je déconseille les variables d'instance au profit des propriétés (comme Apple qui conseille la même chose aux WWDC), en particulier pour toutes les subtilités de gestion mémoire que j'ai déjà  évoquées dans plusieurs posts.

    Mais surtout niveau mémoire c'est vraiment inutile.



    Pour reprendre mon analogie, là  tu demandes à  ton carrossier d'acheter une voiture, de la peindre en rouge, et une fois qu'elle est peinte, de récupérer la peinture qu'il a mise sur cette nouvelle voiture pour la mettre sur la tienne à  la place... et pour jeter la nouvelle voiture qui ne sert plus à  rien à  la casse... quel gâchis !



    A la limite tu aurais juste écrit :
    -(void)faireQuelqueChose {<br />
        string=vc.nom;<br />
    }
    
    Et donc éviter de créer un ViewController pour rien et gâcher de la mémoire, ça serait déjà  un poil mieux, mais ça resterait bien compliqué et alambiqué/tordu comme fonctionnement et pas très MVC
  • DrakenDraken Membre
    décembre 2012 modifié #10
    'AliGator' a écrit:


    tu demandes à  ton carrossier d'acheter une voiture, de la peindre en rouge, et une fois qu'elle est peinte, de récupérer la peinture qu'il a mise sur cette nouvelle voiture pour la mettre sur la tienne à  la place... et pour jeter la nouvelle voiture qui ne sert plus à  rien à  la casse... quel gâchis !


    Pourtant ce mode de production a été déployé sur une large échelle dans les pays de l'Est, pendant l'occupation soviétique. Pour satisfaire aux quotas de production malgré le manque de matières premiéres, les usines étaient souvent obligées de Dà‰MONTER les objets finis pour récupérer les composants et les réinjecter en début de chaà®ne. Comme par exemple les chaà®nes d'assemblage des automobiles DACIA.
  • AliGatorAliGator Membre, Modérateur
    'Draken' a écrit:


    Pourtant ce mode de production a été déployé sur une large échelle dans les pays de l'Est, pendant l'occupation soviétique. Pour satisfaire aux quotas de production malgré le manque de matières premiéres, les usines étaient souvent obligées de Dà‰MONTER les objets finis pour récupérer les composants et les réinjecter en début de chaà®ne. Comme par exemple les chaà®nes d'assemblage des automobiles DACIA.
    Ah mais si c'est pour recycler, je dis pas, mais je doute que l'usine en question crée une voiture et la peigne juste pour la démonter. Utiliser une voiture existante qui a déjà  servi, pourquoi pas, en créer une nouvelle exprès pour la démonter, là  c'est tordu image/biggrin.png' class='bbc_emoticon' alt=':D' />
  • Non ce n'est pas tordu, juste l'instinct de préservation. L'une des caractéristiques de la bureaucratie soviétique était la totale déconnexion entre les objectifs de production et la réalité du terrain. Et des sanctions sévères en cas de non-respect des quotas, pouvant aller jusqu'à  une accusation de sabotage industriel, et le passage devant un peloton d'exécution. Oui c'est dingue, aberrant, carrément kafkaà¯en même !
Connectez-vous ou Inscrivez-vous pour répondre.