2009-08-06 1 views
4

Ich habe ein NSDate Objekt erstellt vonNSDate init Frage, bezogen auf die Speicherverwaltung in Objective-C

NSDate *date = [[NSDate alloc] init]; 

Später habe ich das Datum auf das „jetzt“ zurücksetzen wollen, so dachte ich, dass

[date init]; 

oder

date = [date init]; 

könnte die Arbeit tun, aber sie tun es nicht. Stattdessen

[date release]; 
date = [[NSDate alloc] init]; 

funktioniert. Ich bin ein wenig verwirrt darüber, da in der Dokumentation zu - (id) init, heißt es:

Gibt ein NSDate Objekt und das aktuelle Datum und die Uhrzeit initialisiert.

und da date ist bereits vergeben, es sollte nicht nur eine init Nachricht benötigen?

+1

Daten unveränderlich sind und nicht geändert werden können. Wenn Sie jetzt Zeit haben möchten, müssen Sie ein neues Datum erstellen. Siehe Quinns Antwort unten speziell für: init. Es ist immer ein Programmierfehler, init mehr als einmal für ein gegebenes Objekt aufzurufen. –

Antwort

9

Denken Sie an alloc und init als logisch untrennbare Hälften eines Konstruktors. Sie können Methoden, die mit "init" beginnen, nur einmal für ein bestimmtes Objekt aufrufen - nachdem das Objekt initialisiert wurde und es ein Fehler ist, es erneut zu initialisieren. Dies gilt für jedes Objective-C-Objekt, nicht nur für NSDate. NSDate Objekte sind jedoch auch unveränderlich - einmal erstellt, können sie nicht ändern.

Der Grund dieser Code funktioniert, weil Sie eine neue Instanz von NSDate erstellen, die die richtige Sache zu tun. Sie können auch [NSDate date] verwenden, um dasselbe zu erreichen. Sei dir bewusst, dass es ein Objekt zurückgibt, das du (noch) nicht besitzt, also musst du es behalten, wenn du es behalten und es später freigeben musst.

Beachten Sie, dass, wenn Sie ein Objekt von jemandem erhalten, wurde bereits initialisiert wurde. (Wenn nicht, es ist ein Programmierfehler in dem Code, den es vorgesehen, oder ist eine extrem seltene Ausnahme von der Regel.)

+0

Also was ist "idiomatischer" zu Objective-C? Um '[NSDate date]' und 'retain' zu verwenden, oder die obige' [[NSDate alloc] init] 'und' release'? –

+0

Es gibt keinen, der auf der ganzen Linie idiomatischer ist, es hängt nur davon ab, was Sie wollen. Nicht alle Klassen haben jedoch "Convenience Constructor" -Methoden, aber sie haben immer -init ... -Methoden. In jedem Fall behandelt die Convenience-Methode das Alloc/Init für Sie und gibt das Objekt automatisch wieder frei. Einige Leute sind sehr unnachgiebig in Bezug auf die Autorelease, aber ich finde, dass eine vernünftige Verwendung von Autorelease akzeptabel ist und oft den Code vereinfacht. Wenn Sie die Objective-C-Speicherverwaltung nicht vollständig verstehen, ist das erste, was ich studieren würde. –

5

Wenn Sie das aktuelle Datum erhalten möchten, können Sie einfach verwenden:

NSDate * now = [NSDate date]; 

Wenn Sie es behalten möchten, dann retain es.

NSDate * now = [[NSDate date] retain]; 

Sie nicht NSDate mit init zurücksetzen können, ist init nur für das Objekt zum ersten Mal initialisiert wird.

Sie könnten nur einen anderen Termin bekommen:

NSDate * now = [[NSDate date] retain]; 
// use the now object 
// need new date 
[release now]; 
now = [[NSDate date] retain]; 
// once you don't need it release it 
[now release]; 

Die date Nachricht gibt autoreleased Instanz von NSDate, daher der release oder autorelease.

Die autorelease wird für Fälle verwendet, in denen Sie sich nicht darum kümmern müssen, wo genau Sie das Objekt freigeben müssen - es wird in autorelease pool eingefügt. Objekte im Autorelease-Pool werden nach dem Ende der Iteration der Ereignisschleife oder beim Aufrufen der Freigabe im Pool freigegeben ...(Weitere Informationen zur Speicherverwaltung finden Sie in den Apple-Dokumenten.)

Btw. die [NSDate date] ist eine bequeme Methode, es ist wahrscheinlich so etwas wie (nicht gleich sein, genau quaranteed aber funktionell ähnlich):

- (NSDate *)date 
{ 
    return [[[NSDate alloc] init] autorelease]; 
} 
+0

+1, weil ich sehe, dass du noch nicht das Abzeichen "Nekromant" hast. = P –

+0

Ich habe gerade eine andere Frage beantwortet und ich habe diese Frage oben auf der Fragenliste auf der linken Seite bemerkt, also bin ich gesprungen ... aber trotzdem danke – stefanB