timeIntervalSinceDate:

Bonjour tout l'monde.

J'rencontre un p'tit soucis auquel je ne comprends vraiment rien...

Voici mon code :
<br />
-([color=#cd00a5]IBAction[/color])PushShoot:([color=#cd00a5]id[/color])sender<br />
{[color=#008c00]<br />
     //NSLog(@&quot;Shoot&quot;);[/color][color=#3d8389]<br />
[color=#cd00a5]     if[/color][color=#000000] (&#33;[/color]boolTime[color=#000000])[/color][/color]<br />
     {<br />
[color=#3d8389]          debut[/color] = [[color=#7c1fae]NSDate[/color] [color=#460085]date[/color]];[color=#e40000]<br />
[color=#460085]          NSLog[/color][color=#000000]([/color]@&quot;Debut : %@&quot;[color=#000000], [/color][color=#3d8389]debut[/color][color=#000000]);[/color][/color][color=#3d8389]<br />
          boolTime[color=#000000] =&#33;[/color]boolTime[color=#000000];[/color][/color]<br />
     }[color=#cd00a5]<br />
     else[/color]<br />
     {<br />
[color=#3d8389]          fin[/color] = [[color=#7c1fae]NSDate[/color] [color=#460085]date[/color]];[color=#e40000]<br />
[color=#460085]          NSLog[/color][color=#000000]([/color]@&quot;Fin : %@&quot;[color=#000000], [/color][color=#3d8389]fin[/color][color=#000000]);[/color][/color][color=#460085]<br />
[color=#7c1fae]          NSTimeInterval[/color][color=#000000] duree = [[/color][color=#3d8389]fin[/color][color=#000000] [/color]timeIntervalSinceDate[color=#000000]:[/color][color=#3d8389]debut[/color][color=#000000]];[/color][/color]<br />
     }<br />
}<br />






J'ai un EXEC_BAD_ACCESS sur ma ligne avec le NSTimerInterval, qui m'oblige à  redémarrer mon iPhone (ce fameux qLaunchSuccess)

<p>Dans le doc', y'a ça :
timeIntervalSinceDate:



Returns the interval between the receiver and another given date.

- (NSTimeInterval)timeIntervalSinceDate:(NSDate *)anotherDate



Parameters

anotherDate

The date with which to compare the receiver.



Return Value



The interval between the receiver and anotherDate. If the receiver is earlier than anotherDate, the return value is negative.

Availability
  • Available in iOS 2.0 and later.










Il ne me semble pas avoir fait d'erreur, et pourtant, il y en aurait une...

Réponses

  • CéroceCéroce Membre, Modérateur
    Utilises-tu ARC ?

    Si ce n'est pas le cas, il faut écrire:
    <br />
    debut = [[NSDate date] retain];<br />
    




    (Et ne pas oublier le -release correspondant).
  • Merci beaucoup, ça marche, je n'utilise pas ARC, je préfère faire moi-même.

    J'vais tester sur mon vrai projet.



    Une petite explication quand à  ce retain obligatoire, car je ne l'ai pas vu dans la doc.
  • CeetixCeetix Membre
    juillet 2012 modifié #4
    Bah en utilisant
    <br />
    [color=#000000]debut [/color][color=#666600]=[/color][color=#000000] [/color][color=#666600][[[/color][color=#660066]NSDate[/color][color=#000000] date[/color][color=#666600]][/color][color=#000000];[/color]<br />
    [color=#000000]
    
    [/color]



    Ton objet debut est en autorelease. Elle est donc releasé la fin de la runloop. Donc à  ton second appel de methode, tu appel un objet mort. Il faut donc le "maintenir en vie" en incrémentant son retainCount.

    Tu vas donc avoir un retainCount à  2 jusqu'à  la fin de la runloop, puis il passera à  1. tu pourras donc toujours l'utiliser.



    Edit : et ça n'est pas dans la doc car ça n'est pas un principe que tu appliques uniquement à  NSDate mais c'est un principe fondamental du memory management qui s'applique à  toutes tes instances de classe.
  • Indeed.
  • +date est une méthode de commodité. Elle ne fait qu'appeler alloc+init+autorelease.

    Au lieu de faire un retain derrière en plus, vaux mieux directement faire [[NSDate alloc] init];
  • MalaMala Membre, Modérateur
    avec bien sûr un petit...
    <br />
    [debut release];<br />
    debut = nil;<br />
    


    ...une fois que tu as calculé "duree" histoire de faire les choses dans les règles de l'art. image/wink.png' class='bbc_emoticon' alt=';)' />
  • AliGatorAliGator Membre, Modérateur
    juillet 2012 modifié #8
    Sinon bannir les variables d'instance et utiliser des @properties et plus aucun problème.


    // .h<br />
    @interface XXX : UIViewController<br />
    @property(nonatomic, retain) NSDate* dateDebut;<br />
    @property(nonatomic, retain) NSDate* dateFin;<br />
    @end<br />
    <br />
    // .m<br />
    @synthesize dateDebut = _dateDebut, dateFin = _dateFin;<br />
    <br />
    -(void)dealloc<br />
    {<br />
    	// Nettoyage de la mémoire<br />
    	self.dateDebut = nil;<br />
    	self.dateFin = nil;<br />
    	[super dealloc];<br />
    }<br />
    <br />
    // Et ta méthode devient :<br />
    -(IBAction)PushShoot:(id)sender<br />
    {<br />
    	 //NSLog(@&quot;Shoot&quot;);<br />
    	 if (&#33;boolTime)<br />
    	 {<br />
    		  self.debut = [NSDate date];<br />
    		  NSLog(@&quot;Debut : %@&quot;, self.debut);<br />
    		  boolTime =&#33;boolTime;<br />
    	 }<br />
    	 else<br />
    	 {<br />
    		  self.fin = [NSDate date];<br />
    		  NSLog(@&quot;Fin : %@&quot;, self.fin);<br />
    		  NSTimeInterval duree = [self.fin timeIntervalSinceDate:self.debut];<br />
    	 }<br />
    }
    
  • Uhm.. me semblait qu'il fallait éviter d'utiliser les setters/getters dans le -dealloc et -init?
  • AliGatorAliGator Membre, Modérateur
    juillet 2012 modifié #10
    Heu non au contraire. Moi j'utilise des properties partout sans pb.



    Dans le dealloc ça peut se discuter de savoir si tu veux déclencher le KVO ou pas, si tu utilises du KVO et qu'en plus tu codes comme un porc ton KVO tu peux avoir des effets de bord oui, mais si tu codes propre, aucun souci.
  • Et qu'appelles-tu coder comme un porc ?
  • AlakAlak Membre
    juillet 2012 modifié #12
    Donc vaut mieux :


    <br />
    -(void)dealloc<br />
    {<br />
    		// Nettoyage de la mémoire<br />
    		self.dateDebut = nil;<br />
    		self.dateFin = nil;<br />
    		[super dealloc];<br />
    }<br />
    




    que


    <br />
    -(void)dealloc<br />
    {<br />
            // Nettoyage de la mémoire<br />
    		[_dateDebut release];<br />
    		_dateDebut = nil;<br />
    		[_dateFin release];<br />
    		_dateFin = nil;<br />
            [super dealloc];<br />
    }<br />
    




    Ou c'est exactement la même chose ?
  • AliGatorAliGator Membre, Modérateur
    C'est pratiquement la mm chose, sauf que l'appel aux propriétés via "self.xxx = nil" est potentiellement thread-safe (si tes propriétés sont atomiques) et gèrent le KVO, alors que release+nil ne le font pas.
  • 'AliGator' a écrit:


    Heu non au contraire. Moi j'utilise des properties partout sans pb.



    Dans le dealloc ça peut se discuter de savoir si tu veux déclencher le KVO ou pas, si tu utilises du KVO et qu'en plus tu codes comme un porc ton KVO tu peux avoir des effets de bord oui, mais si tu codes propre, aucun souci.




    Mouais, ça fait parti des grands débats qu'on peut trouver sur le net.. Perso je reste sur les conseils d'Apple, cà d éviter d'utiliser les getters/setters dans un init/dealloc. Sauf si réellement nécessaire. Dans le cas actuel je ne vois pas l'intérêt de déroger aux conseils d'Apple.
  • AliGatorAliGator Membre, Modérateur
    Pour le dealloc je comprend le débat, y'a 2 écoles, chacun son truc.



    Par contre pour le init j'ai jamais vu de dépréciation d'utiliser des getter/setters dans le init ?! Tu tiens ça d'où ? Et je ne vois pas en quoi ça serait un problème en plus...
  • juillet 2012 modifié #16
    Me semblait avoir lu ça dans la doc à  un moment (j'arrive plus à  remettre la main dessus).

    De toute façon on ne peut typiquement pas y échapper tout le temps dans le -init, surtout lorsqu'on sous-classe des objets de UIKit (exemple typique avec une UIScrollView qu'on veut configurer dès son instanciation)

    Mais j'ai sûrement rêvé.. image/biggrin.png' class='bbc_emoticon' alt=':D' /> Parce qu'effectivement je ne vois aucune raison valable.. Quand bien même je préfère appliquer le procédé suivant:


    <br />
    -(id)initWithDictionary:(NSDictionary *)dictionary<br />
    {<br />
    self = [super init];<br />
    if(self){<br />
    _myDictionary = [dictionary copy];<br />
    }<br />
    return self;<br />
    }<br />
    
  • AliGatorAliGator Membre, Modérateur
    Tu veux dire que tu préfères faire une copie qu'un retain ? Alors que ta @property, elle, est en "retain" ? Donc tu ne respectes pas ta policy de ta property ? (A moins que dans ta tête ta @property était en copy et pas retain ?)



    Bon comme je pense qu'Apple est suffisament intelligent dans son implémentation des NSObjects de CoreFoundation, je pense qu'ils ont fait du CoW sur les NSObjects, et donc que sur les objets immutable, retain et copy doivent être synonymes, mais bon, faut pas se baser sur cette assomption non plus !



    Et ça veut dire aussi que si tu changes la policy de ta property dans le .h... faut que tu penses à  changer dans le ou les "init" pour être cohérent ! Alors qu'avec l'accesseur, pas besoin. Et en plus avec l'accesseur c'est thread-safe (et KVO-compliant)
  • AliGatorAliGator Membre, Modérateur
    Heu super mais j'aimerais bien savoir pourquoi ?!

    Comme je l'ai dit dans le dealloc je peux comprendre, ça a ses avantages et ses inconvénients, ça se discute, mais au moins je comprend pourquoi il y a débat.

    Dans le init, je ne vois vraiment pas le problème.
  • 'AliGator' a écrit:


    Tu veux dire que tu préfères faire une copie qu'un retain ? Alors que ta @property, elle, est en "retain" ? Donc tu ne respectes pas ta policy de ta property ? (A moins que dans ta tête ta @property était en copy et pas retain ?)




    Heu non.. j'ai pas écris la property là  mais dans ma tête elle était décrite en "copy". C'est juste pour montrer que je n'utilise pas le setter.
  • juillet 2012 modifié #21
    'AliGator' a écrit:


    Heu super mais j'aimerais bien savoir pourquoi ?!

    Comme je l'ai dit dans le dealloc je peux comprendre, ça a ses avantages et ses inconvénients, ça se discute, mais au moins je comprend pourquoi il y a débat.

    Dans le init, je ne vois vraiment pas le problème.




    Apparemment si


    The main issue is what happens when someone subclasses you class and overrides your accessor methods. If you call them from your class' -init method, the subclass' implementation of the accessor will be called *before* the subclass' -init method has completed. There is a great potential for confusion and errors if that accessor relies on state that is set up in -init. The same thing (in reverse) will happen in dealloc; the accessor will be called *after* the subclass' -dealloc has finished, and may be relying on state that has already been torn down.




    https://devforums.apple.com/message/668924
  • AliGatorAliGator Membre, Modérateur
    Ah ouais, cas alambiqué quand même... Et qui n'est valable que si on surcharge les accesseurs dans la classe fille tout en dépendant d'une variable qu'on aurait initialisée après la propriété dans le init... Bon ok, je veux bien. Mais faut en vouloir pour tomber sur ce cas !
  • 'AliGator' a écrit:


    Ah ouais, cas alambiqué quand même... Et qui n'est valable que si on surcharge les accesseurs dans la classe fille tout en dépendant d'une variable qu'on aurait initialisée après la propriété dans le init... Bon ok, je veux bien. Mais faut en vouloir pour tomber sur ce cas !




    J'suis entièrement d'accord ^^
Connectez-vous ou Inscrivez-vous pour répondre.