Problème NSDate
Rocou
Membre
Mon programme plante sans que je comprenne pourquoi. J'y suis depuis midi et je commence à désespérer
Voici mon code (simplifié):
Ce qui est important: j'initialise une zone avec une NSDate. A priori, ça fonctionne très bien.
Et maintenant, l'affichage:
ça fonctionne très bien... Une seule fois. Quand drawRect est appelé une nouvelle fois, le programme plante. C'est à l'utilisation de "maDate" que le programme plante. En face de "maDate", le debugger indique invalid.
:why?:
Voici mon code (simplifié):
- (id)initWithFrame:(NSRect)rect {<br /> self = [super initWithFrame:rect];<br /> if (self) <br /> {<br /> <br /> //préparation du tracé du calendrier<br /> //___________________________________<br /> <br /> NSRect bounds = [self bounds]; <br /> largeurColonneDefaut=90; <br /> nbColonnesAffichees = 50; //pour être sûr de dépasser la largeur d'un écran.<br /> NSDate *ladate = [NSDate date];<br /> NSTimeInterval secondsPerDay = 24 * 60 * 60;<br /> <br /> <br /> coul = [NSColor blackColor];<br /> ColArray = [[NSMutableArray alloc] initWithCapacity:(nbColonnesAffichees)];<br /> <br /> x=0;<br /> y=0;<br /> for(int i =0; i<nbColonnesAffichees; i++)<br /> {<br /> Calendrier *uneColonne = [[Calendrier alloc]init];<br /> [uneColonne initWithPosX:x PosY:y TWidth:largeurColonneDefaut THeight:bounds.size.height withColor:coul andSelect:NO];<br /> <br /> //l'entete<br /> [uneColonne initLigneEntete:x PosY:y TWidth:largeurColonneDefaut THeight:20 withColor:coul withDate:ladate];<br /> //On incrémente la date<br /> ladate = [ladate addTimeInterval:secondsPerDay];<br /> <br /> [ColArray addObject:uneColonne];<br /><br /> <br /> x = largeurColonneDefaut + i * largeurColonneDefaut;<br /> [uneColonne release];<br /> }<br /> }<br /> return self;<br />}<br />
Ce qui est important: j'initialise une zone avec une NSDate. A priori, ça fonctionne très bien.
Et maintenant, l'affichage:
NSDateFormatter *dateFormatter;<br />...<br /><br />- (void)drawRect:(NSRect)rect {<br /> <br /> <br /> NSRect bounds = [self bounds];<br /> <br /> NSString *maDate=@"";<br /> <br /> int i;<br /> //On dessine le calendrier<br /> CGFloat hauteurColonne = bounds.size.height;<br /> <br /> for(i =0;i<nbColonnesAffichees;i++)<br /> {<br /> <br /> // objet va recevoir les informations de chaque location <br /> Calendrier *uneColonne = [ColArray objectAtIndex:i];<br /> <br /> // on dessine un rectangle grâce au informations détenu par uneLocation <br /> NSRect laColonne = NSMakeRect([uneColonne abs_value], [uneColonne ord_value], [uneColonne largeur_value],hauteurColonne);<br /> <br /> // chaque rectangle existant (chaque colonne) est dessiné <br /> [[NSColor whiteColor] set];<br /> NSRectFill(laColonne);<br /> [[NSColor blackColor] set];<br /> NSFrameRectWithWidth ( laColonne, 0.1 ); <br /> <br /> //On dessine la ligne d'entête (qui est en fait une succession de rectangle d'entête)<br /> Calendrier *uneEntete = [ColArray objectAtIndex:i];<br /> <br /> // on dessine un rectangle grâce aux informations détenues par uneEntete <br /> NSRect lEntete = NSMakeRect([uneEntete x_entete_value], [uneEntete y_entete_value], [uneEntete largeur_entete_value],[uneEntete hauteur_entete_value]);<br /> [[NSColor lightGrayColor] set];<br /> NSRectFill(lEntete);<br /> [[NSColor blackColor] set];<br /> NSFrameRectWithWidth ( lEntete, 0.1 ); <br /> <br /> <br /><br /> //Le texte des entetes<br /> dateFormatter =[[[NSDateFormatter alloc] init] autorelease];<br /> [dateFormatter setDateStyle:NSDateFormatterShortStyle];<br /> [dateFormatter setTimeStyle:NSDateFormatterNoStyle];<br /> maDate = [dateFormatter stringFromDate:uneEntete.date_entete];<br /> <br /> <br /> [maDate drawAtPoint:NSMakePoint([uneEntete abs_value]+((lEntete.size.width - 40)/2),[uneEntete ord_value]+2) withAttributes:nil];<br /> <br /> }<br /> <br />}<br />
ça fonctionne très bien... Une seule fois. Quand drawRect est appelé une nouvelle fois, le programme plante. C'est à l'utilisation de "maDate" que le programme plante. En face de "maDate", le debugger indique invalid.
:why?:
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Merci Tablier. Cependant, je n'ai pas l'impression de les modifier. Elles sont créées dans le initFrame puis elles sont lues.
Dans initFrame j'ai bien:
ladate = [ladate addTimeInterval:secondsPerDay]; qui ne semble pas correct mais même en supprimant cette ligne, le problème reste le même.
Essaye de déclarer un NSMutableString en dehors de drawRect, avec alloc / init ...
et son release en Dealloc.
Merci mais ça plante de la même façon
Merci, le voici:
http://dl.free.fr/ujqFjpKhH
@01/01/09 à la place et bien ça plante plus...
[maDate setString: [dateFormatter stringFromDate:uneEntete.date_entete]];
Oui, c'est ce que je disais au début du fil. Je peux mettre directement des chaà®nes, des nombres, ça ne plante pas.
Mais comment convertir une NSDate en string sans dateFormatter?
J'ai bien essayé ceci: maDate = [NSString stringWithFormat:@%d,uneEntete.date_entete];
mais ça plante tout autant.
D'ailleurs ça m'a l'air d'être un beau sac de noeuds, je ne comprends pas tes allocations dans la fonction drawRect, je ne suis assez sûr de moi pour te conseiller, mais il me semble que le model MVC n'est pas respecté.
Au redraw, dateFormater plante parce qu'il va cherché dans un tableau vide, (que tu viens juste d'alloué)...
Qu'est-ce que tu ne comprends pas?
Ce genre de ligne?:
Calendrier *uneEntete = [ColArray objectAtIndex:i];
Je créée une instance de Calendrier que j'initialise avec le contenu d'une case d'un tableau d'objets (des instances de Calendrier).
J'ai grandement pompé sur un source de ceetix, peut-être ai-je mal adapté son code, je suis en train de tester des choses (le graphisme) que je n'avais jamais abordé.
Cela dit, j'ai testé ton idée concernant le dateFormatter mais ça plante toujours
mon tableau ColArray se viderait entre deux appels de drawRect?
Ce qui m'ennuie le plus, c'est que je n'ai pas d'idée pour contourner ce problème insoluble (pour moi).
Le redessin doit prendre les infos dans le model mais pas créer une nouvelle instance.
Si tu place un breakpoint sur [maDate setString: [dateFormatter stringFromDate:uneEntete.date_entete]];
Tu pourras remarquer qu'au redraw ton tableau uneEntete est vide et c'est ça qui plante cette ligne.
Je comprends ce que tu veux dire mais même si je ne crée aucune instance et que j'utilise directement [ColArray objectAtIndex:i], ça plante tout autant.
J'ai trouvé un "tourne-autour" afin d'avancer en générant directement mes date dans le drawRect mais ça m'oblige à revoir l'analyse de mon projet et surtout j'aimerais bien comprendre pourquoi mon tableau se vide entre deux appels à drawRect (et pas tout le tableau car les coordonnées des rectangles que je dessine, qui sont des données du même tableau, sont toujours présentes...)
Merci beaucoup pour le temps passé. Si tu as une autre idée, je suis preneur!
uneEntete.date_entete est invalid car releasé
Bon, ton code c'est
C'est quoi ces variables globales ?
NSInteger largeurColonneDefaut;
NSDateFormatter *dateFormatter;
NSMutableString *maDate=@"";
et
maDate = [[NSMutableString alloc]init];
ne sert à rien...
Et on initialise les variables d'instance dans init !
Ca plante à cause de ça (pas de retain):
largeur_entete = w;
hauteur_entete = h;
couleur_entete = c;
Potasse bien la gestion mémoire car tu ne va pas t'en sortir sinon...
Enfin, je te conseillerais de ne pas utiliser les property et de tout gérer à la main, pour bien comprendre comment fonctionne la gestion mémoire dans les accesseurs.
[EDIT]
une méthode init ce fait comme ça:
Ca devrait aller mieux, pas tester car je n'utilise pas Xcode 3
D'accord mais en faisant directement appel au tableau colArray, je devrais retrouver mes infos, non?
Et pourquoi uneEntete.x_entete (par exemple) n'est pas releasé?
Tout ceci vient de mes innombrables tests. A l'origine, c'était plus propre
En effet, je ne comprends pas grand chose à cette satanée gestion de la mémoire.
Où dois-je mettre mon retain? J'ai tenté d'en mettre à chacune de mes allocations, juste pour voir, ça plante toujours au même endroit.
Bon, ça ne passe pas du tout à la compilation (return avec void? self.couleur_entête??)
Je vais bosser l'idée.
Curieux ! pas de params en init et deux init derrières, plus pas de retain sur les objets et pas de dealloc non plus !
Enfin, tu n'as pas d'objet Controller dans ton projet et c'est pour ça que ton code est un vrai bazar ...
Oui, j'aurais pu faire tout dans un seul init mais bon, ce n'est pas ça qui fait planter mon code. J'ai voulu tester à la va vite les fonctions graphiques.
J'ai ajouté des retain, cela ne change rien. Par contre, j'ai bien des release (cf la fin de la boucle for())
Bah si, mon contrôleur s'appelle MonPlanning.
@interface MonPlanning : NSView
::)
En quoi n'est-ce pas bon?
Ha ok. Merci. Bon je vais tout réécrire.
Sage résolution
Et je commencerais par définir la classe modèle (données), ce que tu n'as même pas fait !
Par ex :
class Location
{
NomLocation,
NomLocataire,
DateDébut,
DateFin
}
puis le nom des locations (un simple tableau ?)
{ Trifouilli les oies, Perpette les bains}
Implémenter le NSCoding pour la sauvegarde.
Toutes ces classes n'ont pas d'informations de positions, c'est le problème de la vue.
C'est le Controlleur qui fournira à la vue (Planning) les données à afficher.
MVC powa
L'analyse est faite et je ne crois pas être trop mauvais dans ce domaine
Le code que tu as pu voir est écrit uniquement pour découvrir comment fonctionne le graphisme.
Inutile, tout est stocké dans une base de donnéees PostgreSQL
Ha oui, je comprends, j'ai effectivement fait n'importe quoi
Merci!
Pour les événements, il suffit de créer un tableau mutable et dessiner les éléments en comparant la date dans la boucle de dessin.
C'est très perfectible mais ça peut te donner des idées pour avancer...
Edit: En fait il manque le modèle, l'appController devrait changer la date de début dans le modèle...