2009-03-25 10 views
2

Die Funktion bei Ich suche nach:Zuweisen von Werten zu Instanzvariablen in Objective C

-(void)viewDidLoad { 
    NSBundle *bundle = [NSBundle mainBundle]; 
    NSString *plistPath = [bundle pathForResource:@"statedictionary" ofType:@"plist"]; 

    NSDictionary *dictionary = [[NSDictionary alloc] initWithContentsOfFile:plistPath]; 
    self.statesZips = dictionary; 
    [dictionary release]; 

    NSArray *components = [self.stateZips allKeys]; 
    NSArray *sorted = [components sortedArrayUsingSelector:@selector(compare:)]; 
    self.States = sorted; 

    NSString *selectedState = [self.states objectAtIndex:0]; 
    NSArray *array = [stateZips objectForKey: selectedState]; 
    self.zips = array; 
} 

Warum ist ein NSDictionary zugeordnet, dann zugewiesen zu einem Zeiger * Wörterbuch genannt, und dann auf die Instanzvariable stateZips zugewiesen? Warum sollte es nicht zugewiesen und der Instanzvariablen direkt zugewiesen werden, um Speicher für das Erstellen und Freigeben eines anderen NSDictionary zu sparen? Die gleiche Methode wird immer gefolgt, auch später in dieser Funktion mit der NSArray ...

NSDictionary *dictionary = [[NSDictionary alloc] initWithContentsOfFile:plistPath]; 
self.statesZips = dictionary; 
[dictionary release]; 

Auch stellt diese Sortierung die Schlüssel aus einer Hash-Tabelle (Wörterbuch) in alphabetischer Reihenfolge. Ich bin mir nicht sicher, ob ich diese Zeile verstehen:

NSArray *sorted = [components sortedArrayUsingSelector:@selector(compare:)]; 

Antwort

6

scheint niemand die Tatsache angesprochen zu haben, dass die Linie

self.statesZips = dictionary; 

ist nicht direkt eine Instanz Variablenzuweisung.stateZips ist eine Eigenschaft, und diese Codezeile ruft die Methode setStateZips: auf. Diese Methode behält oder kopiert das Wörterbuch, so dass es nicht mehr benötigt wird, es sei denn, die Methode viewDidLoad beabsichtigt, sie für einen bestimmten Zweck erneut zu verwenden. Das macht es OK zu release es.

Die vorherige Zeile:

[[NSDictionary alloc] initWithContentsOfFile:plistPath]; 

zuweist, ein Objekt. Das macht es zu Ihrer Verantwortung, release es, sobald Sie es nicht mehr brauchen. Nachdem es der statesZips-Eigenschaft zugewiesen wurde, wird es nicht mehr benötigt, daher ist es freigegeben und Sie sollten dictionary nicht mehr verwenden. Sie werden feststellen, dass sich der spätere Code nur auf self.stateZips bezieht, nicht auf dictionary.

Im Fall der NSArray später in der Methode, viewDidLoad nicht das Objekt zuweisen, so dass diese Methode nicht für den Aufruf release darauf verantwortlich ist. Die Faustregel ist, dass wenn Sie alloc es sind, Sie dafür verantwortlich sind, sicherzustellen, dass es veröffentlicht wird. Ansonsten ist es nicht dein Problem.

Beim Sortieren des Arrays wird die Methode sortedArrayUsingSelector: verwendet. Ein Selektor identifiziert eine Methode in Objective-C. Und die @selector ist die literale Syntax für Selektoren (ähnlich wie @"" ist die literale Syntax für NSString Objekte). Also, was dieser Code sagt, ist "geben Sie mir ein Array, wo die Objekte in components sind sortiert, und verwenden Sie die compare:-Methode, um jedes Objekt zu vergleichen, wenn Sie die Sortierung. Wenn es das Array sortiert, ruft es compare: auf die Objekte in Das Array, um zu bestimmen, wie man sie in Ordnung bringt.

+1

Ich denke eigentlich, dass die Semantik beibehalten/zuweisen der statesZips-Eigenschaft ist irrelevant. Der Code weist ein Objekt zu und muss es freigeben, * unabhängig * von der Semantik von statesZips, es sei denn, es wird in einer Umgebung mit Garbage Collection ausgeführt. –

+0

@Barry Wark: Nun, nein. Die Semantik von StatesZips ist sehr relevant. Wenn diese Methode das Dictionary nicht beibehalten oder kopieren würde, würde der Zugriff auf statesZip nach Zeile 7 zu undefiniertem Verhalten führen (wahrscheinlich ein segfault). – hop

+0

Convenience-Funktionen wie initWithContentsOfFile sind automatisch freigegeben. –

4

Die statesZips Eigenschaft wahrscheinlich gehalten wird, das ist die Argumentation.

Wenn das NSDictionary zum ersten Mal zugewiesen wird, ist seine Retain-Anzahl 1. Wenn es statesZips zugewiesen wird, wird die Retain-Anzahl 2. Wenn es freigegeben wird, sinkt die Retain-Anzahl auf 1, was normalerweise das gewünschte Ergebnis ist.

Beachten Sie, dass der folgende Code würde produziert haben (fast) das gleiche Ergebnis:

self.statesZips = [NSDictionary dictionaryWithContentsOfFile:plistPath]; 

weil dictionaryWithContentsOfFile kehrt ein Autoreleased Objekt.

Als Klassenmethode geben Klassenmethoden wie [NSDictionary dictionary] automatisch freigegebene Objekte zurück (die nach einiger Zeit automatisch freigegeben werden), während die übliche Methode "alloc-init" (wie in [[NSDictionary alloc] init]) beibehaltene Objekte zurückgibt.

Ich schlage vor, Sie Memory Management Programming Guide for Cocoa für weitere Informationen lesen.

EDIT: Ich muss den letzten Teil Ihrer Frage verpasst haben, als ich es zuerst las, aber Barry hat diesen Teil bereits beantwortet.

2

Dieser Code verwendet Referenz-gezählten Speicherverwaltung (nicht die automatische Garbage Collection Speicherverwaltung in Objective-C 2.0 auf OS X). Wenn ein Objekt (in diesem Fall NSDictionary und NSArray) zugewiesen ist, ist der Aufrufer für den Aufruf von -release für diese Instanz verantwortlich. Wenn die Freigabe nicht erfolgt, tritt ein Speicherverlust auf. Der Code haben könnte als

geschrieben
self.statesZips = [[[NSDictionary alloc] initWithContentsOfFile:plistPath] autorelease]; 

aber auf Kosten der weniger expliziten Speicherverwaltung (unter Berufung auf NSAutoreleasePool zur Freigabe der alloc'd Instanz am Ende der Veranstaltung Schleifeniterationslatenzzeit.

der Anruf

[components sortedArrayUsingSelector:@selector(compare:)]; 

gibt ein Array, dessen Elemente stammen aus components sondern nach der Rückgabewert des Aufrufs [elem1 vergleichen: elem2]. zwei Array-Elemente vergleichen

+0

+1 für die eigentliche richtige Antwort auf die gestellte Frage.Die Semantik der StatesZip-Eigenschaft ist hier irrelevant.Der Grund für das Muster ist Code Lesbarkeit und explizite Speicherverwaltung als Du beschreibst Apple, für ARC, so dass wir immer weniger von diesen Fragen bekommen werden (ich denke, der Zugriff auf Blockvariablenfragen ist die neue Retain/Release-Frage) – ikuramedia

Verwandte Themen