[Presence 2] Ai-je bien passé ma variable d'instance à  mon autre classe ?

CrazyJoCrazyJo Membre
02:42 modifié dans API UIKit #1
Salut !

Je continue mon apprentissage sur l'iPhone et la programmation toujours tout en suivant les cours de Stanford. J'en suis au 8ème cours sur les tableview et suit actuellement le TP sur Twitter (Presence Part 2).

En gros l'application doit aller récolter l'image , le prénom et les statuts d'un membre dont on connaà®t son username stocké dans un .plist. Une première vue est une tableview affichant les photos et les username. Lorsque l'on clique sur un username une seconde vue apparaà®t affichant ses derniers statuts.

L'une des consignes de l' "Assignment-Presence 2 .pdf " est :
In Presence 1, we pushed a PersonDetailViewController onto the navigation stack in our button's
action method. Now, we're going to do it in response to a table selection. You remember how to
do that, right? Your PersonDetailViewController class should now have a “person” property. Be
sure to set it on the instance after creation, before you push it onto the stack.

La partie en gras est mon problème. Mon application fait bien ce qui est demandé mais je ne sais pas si je l'ai fait de manière propre. C'est pourquoi je vous demande de jeter un petit coup d'oeil au quelques lignes de codes de mon projet. Plus précisément je ne sais si je gère bien l'utilisation de la classe "Person" et si je passe correctement mes variables d'instances d'une classe à  l'autre.

Ici encore un bref aperçu du code :
PersonListViewController.m
<br />// Person instance<br />	person = [[Person alloc]initWithName:nil userName:[users objectAtIndex:indexPath.row] withImage:nil];<br />	<br />	// Load details view<br />	PersonDetailsViewController *personDetailsViewController = [[PersonDetailsViewController alloc]initWithStyle:UITableViewStyleGrouped andPerson:person];<br />[...]<br />// Release<br />[person release];<br />


et encore dans PersonDetailsviewController.h :
<br />@class Person;<br /><br />@interface PersonDetailsViewController : UITableViewController {<br />	NSString *username;<br />}<br />- (id)initWithStyle:(UITableViewStyle)style andPerson:(Person *)iperson;<br />@end<br />

dans PersonDetailsviewController.m :
<br />- (id)initWithStyle:(UITableViewStyle)style andPerson:(Person *)person {<br />	<br />	self = [super initWithStyle:style];<br />	if (self) {<br />		NSLog(@&quot;Cool !&quot;);<br />		NSLog(@&quot;%@&quot;,[person userName]);<br />		username = [[NSString alloc]initWithFormat:[person userName]];<br />	}<br />	return self;<br />}<br />


le mieux est de voir directement dans le .xcodeproj je crois.

Merci

Réponses

  • CrazyJoCrazyJo Membre
    02:42 modifié #2
    Bon alors apparemment ça ne choque personne donc j'ai juste ? On passe bien un object à  un autre classe comme j'ai fais.

    (A part qu'il manque 2 releases dans le projet zippé )

  • muqaddarmuqaddar Administrateur
    02:42 modifié #3
    hum... mmph

    Your PersonDetailViewController class should now have a “person” property


    Pour moi ça sous-entend dans le .h :

    @property(nonatomic, retain) Person *person;
    


    et dans le .m

    <br />@synthetize person;<br /><br />- (id)initWithStyle:(UITableViewStyle)style andPerson:(Person *)aPerson {<br />	<br />	self = [super initWithStyle:style];<br />	if (self) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  person = [aPerson retain];<br />	}<br />	return self;<br />}<br />
    
  • SmySmy Membre
    02:42 modifié #4
    J'avance aussi sur Presence 2, et je vais bientôt pouvoir envoyer mes sources. Je n'ai malheureusement pas beaucoup de temps en ce moment...

    J'ai eu le même problème que toi de core dans le cas d'ajout d'un utilisateur dans le plist, et il y a deux raisons :

    <br />	NSDictionary *infoUser = [TwitterHelper fetchInfoForUsername:username];<br />
    

    Pense à  tester le retour (et donc que infoUser ne soit pas nil) avant de continuer sur le user

    Dans TwitterHelper.h :
    <br />#define USE_TEST_SERVER 1<br />
    

    Il faut le passer à  0 pour faire des requêtes sur la production de Twitter, sinon il fonctionne sur le serveur de Stanford, et tu ne trouveras jamais tes amis !

  • AliGatorAliGator Membre, Modérateur
    02:42 modifié #5
    Notez une astuce puisque tu parles de NSDictionary qui peut être nil : moi j'utilise souvent la méthode +dictionaryWithDictionary: (et +arrayWithArray: poru les NSArrays) dans ce genre de cas.

    Au début je ne comprenais pas l'intérêt de ces méthodes, qui crée un dictionary à  partir d'un dictionary existant... autant faire un simple égal "=" (ou plutôt à  la limite un copy+autorelease) sur le dictionary, non ?
    Eh eh et ben non, parce que si l'argument est nil, ça crée un NSDictionary (resp. NSArray) vide !

    [NSDictionary dictionaryWithDictionary:nil] --> retourne un NSDictionary non-nil, mais vide (count=0)
    [NSDictionary dictionaryWithDictionary:d] --> retourne une copie de d, avec les mêmes éléments (ou un NSDico vide si d est nil)
  • CrazyJoCrazyJo Membre
    02:42 modifié #6
    @muqaddar: Merci  :p

    @Smy : Mouarf, je savais que c'était tout con, c'était en plus écrit dans les commentaires du code source... :o . Merci ! 

    Moi aussi je tourne en ralentit cette semaine, j'en suis à  cette partie du tuto "presence " :
    Displaying status updates in a table view
    The big challenge here is the fact that status messages require varying amounts of vertical
    space. Luckily, there's a UITableView delegate method for specifying the height of each row. To
    compute the height of your text, use the methods from UIStringDrawing.h. In a table view
    with the grouped style, the cell is inset by 10 pixels from the edges, and the text is inset by an
    additional 10 pixels. UITableViewYou'll also need to customize the contentView of your table
    view cell by adding your own smultiline text by default.

    ... et c'est pas simple. :crackboom:-
  • SmySmy Membre
    juin 2009 modifié #7
    Et voilà , ma version en PJ...

    J'ai des légers memory leak à  trouver, mais sinon c'est terminé.

    @AliGator
    Du coup, tu ne testes jamais les retours, mais tu te bases sur le comportement d'un dictionary vide ?

    @CrazyJo
    Quand tu ajoutes un projet à  un post, pense à  nettoyer les objets avant de le zipper (Build/Clean all target), ou même supprime le contenu du dossier Build.

    Dodo :)


    [Edit]: Ne pas prendre cette version mais celle plus bas...
  • SmySmy Membre
    02:42 modifié #8
    dans 1244671983:

    J'ai des légers memory leak à  trouver, mais sinon c'est terminé.

    Bon, en fait, non, ce n'est pas terminé, j'ai un joli bug de scroll vertical sur la seconde view. Mmmmhhhhh !
  • SmySmy Membre
    02:42 modifié #9
    Corrigé, pas simple...

    CrazyJo, tu as terminé ?
  • CrazyJoCrazyJo Membre
    02:42 modifié #10
    Arg ! Désolé !  :o J'avais pas prévenu mais je suis partis quelque jours à  Berlin et je viens de rentrer. Je vais regarder ça. Merci beaucoup !
  • AliGatorAliGator Membre, Modérateur
    02:42 modifié #11
    dans 1244671983:
    @AliGator
    Du coup, tu ne testes jamais les retours, mais tu te bases sur le comportement d'un dictionary vide ?
    Bah en fait ça dépend du besoin.

    Mais souvent je veux partir par exemple d'un NSDictionary existant (ou pas) pour lui rajouter des clés, par exemple. Dans ce cas je crée un NSMutableDictionary à  partir de ma variable de type NSDictionary... sauf que si je fais ça avec un code genre
    NSMutableDictionary* monDicoModifiable = [monDico mutableCopy];<br />[monDicoModifiable setValue:@&quot;toto&quot; forKey:@&quot;tata&quot;];<br />[self setNewDico:monDicoModifiable]; // par exemple, imaginons<br />[monDicoModifiable release]; // on a fait une &quot;copy&quot; donc faut penser à  releaser !<br />
    
    ... ben si ma variable monDico est à  nil, monDicoModifiable vaudra nil aussi (l'envoi d'un message à  nil n'a pas d'effet et retourne nil/NULL/0)... du coup le setValue:forKey: n'aura pas d'effet non plus, et on se retrouvera encore avec un dico vide à  l'arrivée... alors que de prime abord on s'attend plutôt à  finir avec un dico avec juste la clé @tata et sa valeur "@toto si on est parti de rien....

    Donc dans ce genre de cas plutôt que de tester si monDico est nil ou pas avant de créer la mutableCopy, je trouve qu'il est tout aussi voir plus simple de créer un NSMutableDictionary en demandant "en récupérant les données de l'ancien" comme ça s'il n'est pas nil, on repart de la même base... mais s'il est nil car n'a encore jamais été affecté/alloué, bah on part d'un NSMutableDico vide, mais existant (non-nil) :
    NSMutableDictionary* monDicoModificable = [NSMutableDictionary dictionaryWithDictionary:monDico];<br />[monDicoModifiable setValue:@&quot;toto&quot; forKey:@&quot;tata&quot;];<br />[self setNewDico:monDicoModifiable];
    
    Et là  non seulement on a pas à  ne pas oublier le "release", puisqu'on crée clairement un objet autoreleased avec dictionaryWithDictionary, mais surtout si monDico est nil, pour monDIcoModifiable ça fera comme si monDico existait mais était vide... ce qui en l'occurrence est le comportement qui nous intéresse, puisqu'on veut y rajouter des valeurs, donc faut que monDicoModifiable ne soit pas nil mais bien un dico alloué (vide éventuellement, mais existant).


    Après bien sûr ça ne s'applique pas à  tous les cas, y'a des fois où on a quand même besoin, voire ça nous arrange, de tester si la valeur est à  nil. Mais ici c'est plutôt plus simple d'utiliser dictionaryWithDictionary.
    Donc voilà  au moins ça explique aussi l'intérêt de ces méthodes (plutôt que d'envoyer un simple retain, copy ou mutableCopy au dico, ce qui retournera nil si le dico de depart est nil).
Connectez-vous ou Inscrivez-vous pour répondre.