AppDelegate NSString (Null)

Bonsoir,

j'ai créer une classe Raid dans laquelle se trouve un NSString:

Raid.h

@interface Raid : NSObject {

int nbDisk;
NSString *type;
float taille;

}

-(float)calculRaid:(int)nombreDisk:(float)tailleDisk:(NSString *)raidType;

@property (readwrite)int nbDisk;
@property (readwrite, copy) NSString *type;
@property (readwrite) float taille;


J'ai créé une instance dans AppDelegate:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {   
   
    // Override point for customization after app launch.
aRaid = [[Raid alloc]init];
    return YES;
}


Puis dans 2 autres classe: MainViewController et RaidVisualViewController, je voudrais accéder aux propriétés de cette aRaid qui est créer dans AppDelegate:

RaidAppDelegate *appDelegate = (RaidAppDelegate *)[[UIApplication sharedApplication]delegate];

Lorsque je tente de récupérer et d'afficher les valeurs des propriétées de appDelegate.aRaid toutes fonctionnes sauf pour le type (NString) qui me renvoi (Null):

NSLog(@%f, appDelegate.aRaid.taille); -> 36
NSLog(@Type: %@", appDelegate.aRaid.type); -> Type: (null)


Pouvez-vous m'éclairer, j'ai presque tout tenter pour comprendre (en essayant avec les méthodes value:Forkey: même problème... ?)?

Merci pour votre aide.

Réponses

  • lgriffielgriffie Membre
    07:04 modifié #2
    Est-ce que vous pouvez publier le code d'instanciation de la variable NSString ?
  • CéroceCéroce Membre, Modérateur
    07:04 modifié #3
    Pareil que Igriffie.

    Et sinon, vire la méthode -(float)calculRaid:(int)nombreDisk:(float)tailleDisk:(NSString *)raidType.
    Le calcul de la taille doit se faire dans la méthode -[taille].
    (taille de type float ?)
  • macmaniaquemacmaniaque Membre
    07:04 modifié #4
    Voici le code de -(id)init:

    #import "Raid.h"


    @implementation Raid

    @synthesize nbDisk, type, taille;


    -(id)init
    {
    [super init];
    self.type=@";";
    return self;
    }


    de la classe Raid ou est déclaré le type (NSString).
    Pour ce qui est du reste voici la déclaration des propriétées avec leurs type:



    int nbDisk;
    NSString *type;
    float taille;


    @property (readwrite)int nbDisk;
    @property (readwrite, copy) NSString *type;
    @property (readwrite) float taille;



    Enfin, pourquoi virer la méthode calculRaid?

    Merci pour vos réponses!
  • macmaniaquemacmaniaque Membre
    07:04 modifié #5
    Après une nouvelle vérification, je viens de me rendre compte que la propriété type (NSString) n'est pas la seul à  être à  Null, la variable type (appDelegate.aRaid.type) vaut 0 alors qu'elle devrait avoir une autre valeur...

    Voici le code:

    - (IBAction)calculateRaid:(id)sender
    {
    appDelegate.aRaid.nbDisk = [nbDiskField.text intValue];
    appDelegate.aRaid.taille = [tailleDiskField.text doubleValue];

    NSLog(@%i, appDelegate.aRaid.taille);

    int index = [raidPickerView selectedRowInComponent:0];
    //NSLog(@[allRaidType objectAtIndex:index]: %@", [allRaidType objectAtIndex:index]);
    //NSString *leType = (@%@", [allRaidType objectAtIndex:index]);

    //appDelegate.aRaid.type = (@%@", leType);
    //[appDelegate.aRaid setValue:[allRaidType objectAtIndex:index] forKey:@type];

    appDelegate.typeDeRaid = [allRaidType objectAtIndex:index];

    NSLog(@%@", [allRaidType objectAtIndex:index]);

    NSLog(@%i, appDelegate.aRaid.taille);

    //NSLog(@Type: %@", appDelegate.aRaid.type);

    resLabel.text = [NSString stringWithFormat:@%.2f Go, [appDelegate.aRaid calculRaid:appDelegate.aRaid.nbDisk :appDelegate.aRaid.taille :[allRaidType objectAtIndex:index]]];



    NSLog(@res: %@", resLabel.text);

    [resLabel setHidden:NO];
    }

    Output:

    [Session started at 2010-04-26 08:57:55 +0200.]
    2010-04-26 08:57:59.636 Raid[394:207] 0
    2010-04-26 08:57:59.637 Raid[394:207] 0
    2010-04-26 08:57:59.638 Raid[394:207] 0
    2010-04-26 08:57:59.638 Raid[394:207] res: 0.00 Go
  • CéroceCéroce Membre, Modérateur
    07:04 modifié #6
    dans 1272264447:

    @property (readwrite, copy) NSString *type;

    Déclare plutôt:
    [tt]@property (readwrite, retain) NSString *type;[/tt]
    Une NSString n'est pas modifiable (contrairement à  une NSMutableString), la copier prend juste de la mémoire et du temps.


    dans 1272264447:

    Enfin, pourquoi virer la méthode calculRaid?

    Parce que ce n'est pas de la programmation objet.
    À quoi bon passer tous les paramètres à  calculRaid ? L'objet les connaà®t déjà .
    Donc, le prototype deviendrait quelque chose comme:
    [tt]- (float) calculRaid;[/tt]
    Ce qui n'est pas un nom parlant, et qui en pratique te renvoie taille.
    Fais le calcul directement dans la méthode - [taille].

    dans 1272264447:

    NSLog(@%i, appDelegate.aRaid.taille);

    taille est un float. Il faut que tu passe %f.

    Comment initialises-tu allRaidType ?
  • macmaniaquemacmaniaque Membre
    07:04 modifié #7
    Merci pour toutes ces suggestions !!!

    Voici comment je déclare allRaidType:
    @property (readwrite, retain)NSMutableArray *allRaidType;
    @synthetize allRaidType;

    - (void)viewDidLoad {
    [super viewDidLoad];

    allRaidType = [[NSMutableArray alloc]initWithObjects:@";0", @1, @5, nil];

    }
  • macmaniaquemacmaniaque Membre
    07:04 modifié #8
    çA MARCHE!  :o

    Alors voici mon code:

    - (IBAction)calculateRaid:(id)sender
    {
    if(appDelegate==nil)
    {

    appDelegate = (RaidAppDelegate *)[[UIApplication sharedApplication]delegate];
    }

    appDelegate.aRaid.nbDisk = [nbDiskField.text intValue];
    appDelegate.aRaid.taille = [tailleDiskField.text doubleValue];

    NSLog(@Taille 1:%f, [appDelegate.aRaid taille]);

    int index = [raidPickerView selectedRowInComponent:0];
    //NSLog(@[allRaidType objectAtIndex:index]: %@", [allRaidType objectAtIndex:index]);
    //NSString *leType = (@%@", [allRaidType objectAtIndex:index]);

    //appDelegate.aRaid.type = (@%@", leType);
    //[appDelegate.aRaid setValue:[allRaidType objectAtIndex:index] forKey:@type];

    appDelegate.aRaid.type = [allRaidType objectAtIndex:index];

    NSLog(@%@", appDelegate.aRaid.type);

    NSLog(@taille: %f, appDelegate.aRaid.taille);

    //NSLog(@Type: %@", appDelegate.aRaid.type);

    resLabel.text = [NSString stringWithFormat:@%.2f Go, [appDelegate.aRaid calculRaid:appDelegate.aRaid.nbDisk :appDelegate.aRaid.taille :appDelegate.aRaid.type]];



    NSLog(@res: %@", resLabel.text);

    [resLabel setHidden:NO];
    }


    Explication:
    Pour ce qui est "taille est un float. Il faut que tu passe %f." Tu as tout à  fait raison, cela à  corriger quelque erreurs dans le output.
    Enfin, j'avais déclarer appDelegate = (RaidAppDelegate *)[[UIApplication sharedApplication]delegate]; dans la méthode -(id)init que j'avais réécrit pour l'occasion. Du coup je l'ai déplacé à  une meilleur place... :)

    Je vais maintenant m'attacher à  suivre tes recommandations qui finalement sont complètement vrai ^^

    Encore un GRAND MERCI !
  • AliGatorAliGator Membre, Modérateur
    07:04 modifié #9
    Au passage, ta méthode [tt]-(float)calculRaid:(int)nombreDisk:(float)tailleDisk:(NSString *)raidType;[/tt] est mal formulée. C'est une syntaxe accepté stricto sensu dans le langage Objective-C, mais jamais rencontrée en pratique.

    En effet, tu ne donnes pas de nom à  tes paramètre : le sélecteur (@selector) de ta méthode est "calculRaid:::", et "nombreDisk", "tailleDisk" et "raidType" ne sont que les variables qui vont récupérer les paramètres, mais en Objective-C on donne toujours des noms aux paramètres, devant les ":" qui introduisent lesdits paramètres.

    Ainsi, quand tu vas appeler ta méthode, dans ton cas tel que tu l'as déclarée, tu vas l'appeler sous la forme [tt][calculDisk:3 :6 :@toto][/tt] par exemple. Du coup, l'appel à  la méthode n'est pas du tout lisible/explicite, on ne comprend pas à  quoi correspondent 3, 6 et toto.
    Aucune méthode dans le framework Cocoa n'a ce genre de signature : les conventions en Objective-C seraient plutôt d'avoir une méthode que tu pourrais appeler sous la forme [tt][calculRaidWithNombreDisk:3 tailleDisk:6 raidType:@toto][/tt]
    Mais quitte à  faire plus homogène, autant avoir tout en anglais (parce que là  le franglais "NombreDisk"... hum :P), une méthode propre et courte, donc je préconiserai plutôt cette signature :
    -(float)calculRaidOfType:(NSString *)raidType  disksCount:(int)nombreDisk  diskSize:(float)tailleDisk;
    
    que tu appellerai donc de la manière suivante ensuite :
    [calculRaidOfType:@"toto" disksCount:3 diskSize:6];
    
  • macmaniaquemacmaniaque Membre
    07:04 modifié #10
    Ouha, merci encore pour ce petit cours ;)

    Sinon, je cherche un moyen pour avoir un object qui peut être lisible dans plusieurs classe. Je pensais que cela était possible avec la classe AppDelegate, mais ce n'est pas le cas, lorsque je réaccède à  appDelegate.aRaid, toute les propriétées sont à  0 ou null:

    [self.delegate flipsideViewControllerDidFinish:self];
    RaidAppDelegate *appDelegate = (RaidAppDelegate *)[[UIApplication sharedApplication]delegate];
    NSLog(@Type dans FlipSideView: %f, [appDelegate.aRaid type]);

    alors que je voudrais récupérer la valeurs qui a été assigner sur une autre vue de mon Appli, donc dans un autre UIViewController.
  • lgriffielgriffie Membre
    07:04 modifié #11
    C'est tout a fait possible si tu instancie ton objet Raid et que tu le conserves en mémoire depuis l'AppDelegate.

    <br /><br />#import &quot;Raid.h&quot;<br /><br />@interface RaidAppDelegate: NSObject {<br />&nbsp;  <br />&nbsp;  Raid *aRaid;<br />}<br /><br />@property (nonatomic, retain)Raid *aRaid;<br /><br /><br />J&#39;ai créé une instance dans AppDelegate:<br /><br />@implementation RaidAppDelegate {<br /><br />- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {&nbsp;  <br />&nbsp;  <br />&nbsp; &nbsp; // Override point for customization after app launch.<br />&nbsp;  aRaid = [[Raid alloc]init];<br />&nbsp; &nbsp; return YES;<br />}<br /><br />
    


    Par contre ne pas oublié de faire un release sur ton objet "aRaid".
  • macmaniaquemacmaniaque Membre
    07:04 modifié #12
    mmm d'accord ^^J'y vois un peu plus clair...

    A vrai dire, j'explore un peu ce coté obscure d'AppDelegate, un point sur lequel je me suis jamais pencher... Et je vois qu'il y a beaucoup de chose à  apprendre là -dessus !

    Merci pour votre aide!
  • AliGatorAliGator Membre, Modérateur
    07:04 modifié #13
    En même temps si tu veux un objet avec instance unique accessible de partout dans ton appli, le pattern Singleton est sans doute plus adapté à  ton besoin ?
  • lgriffielgriffie Membre
    07:04 modifié #14
    dans 1272283655:

    En même temps si tu veux un objet avec instance unique accessible de partout dans ton appli, le pattern Singleton est sans doute plus adapté à  ton besoin ?

    J'ai dégainé un peu vite. En effet, tu as raison AliGator, le pattern singleton peut-être utilisé à  condition qu'une seule instance de cet objet ne puisse exister (comme le App Delegate d'ailleurs qui est construit sur ce schema).
  • CéroceCéroce Membre, Modérateur
    07:04 modifié #15
    dans 1272283958:

    (comme le App Delegate d'ailleurs qui est construit sur ce schema).

    Non, UIApplication est un singleton, mais AppDelegate pourrais être instancié plusieurs fois. En pratique, il n'est instancié qu'une fois, à  l'intérieur du XIB, mais ce n'est pas un singleton.


    Sinon, pour les objets de l'interface utilisateur, qui ont besoin d'accéder aux outlets, ils sont souvent instanciés dans  -[application:didFinishLaunchingWithOptions:], mais pour cet objet Raid, pas besoin, alors mieux vaut le faire dans la méthode -[init]:

    @implementation AppDelegate<br /><br />- (id) init<br />{<br />	if(self = [super init])<br />	{<br />		raid = [[Raid alloc] init];<br />	}<br />	<br />	return self;<br />}<br /><br />- (void) dealloc<br />{<br />	[raid release];<br />	<br />	[super dealloc];	<br />}
    
  • lgriffielgriffie Membre
    07:04 modifié #16
    dans 1272284168:

    dans 1272283958:

    (comme le App Delegate d'ailleurs qui est construit sur ce schema).

    Non, UIApplication est un singleton, mais AppDelegate pourrais être instancié plusieurs fois. En pratique, il n'est instancié qu'une fois, à  l'intérieur du XIB, mais ce n'est pas un singleton.


    oui pour AppDelegate il fallait lire UIApplication  :o
  • CéroceCéroce Membre, Modérateur
    07:04 modifié #17
    Y'a pas de mal, il faut juste éviter d'embrouiller les débutants  :o
  • lgriffielgriffie Membre
    07:04 modifié #18
    dans 1272292266:

    Y'a pas de mal, il faut juste éviter d'embrouiller les débutants  :o

    Ce qui m'a embrouillé c'est le faite que pour accéder au AppDelegate j'utilise

    MyAppDelegateClass *appDelegate = (MyAppDelegateClass *)[[UIApplication sharedApplication]delegate];

    donc j'ai fait le raccourci ;)
Connectez-vous ou Inscrivez-vous pour répondre.